Seccomp Kubernetes-en: hasiera-hasieratik jakin behar dituzun 7 gauza

Ohar. itzul.: Zure arreta aurkezten dizugu ASOS.com britainiar konpainiako aplikazioen segurtasun ingeniari senior batek egindako artikulu baten itzulpena. Harekin, Kubernetesen segurtasuna hobetzera bideratutako argitalpen sorta bat hasten du seccomp-en erabileraren bidez. Irakurleei sarrera gustatzen bazaie, egilearen jarraipena egingo dugu eta gai honi buruzko etorkizuneko materialekin jarraituko dugu.

Seccomp Kubernetes-en: hasiera-hasieratik jakin behar dituzun 7 gauza

Artikulu hau SecDevOps-en izpirituan seccomp profilak sortzeko argitalpenen lehena da, magia eta sorginkeriara jo gabe. XNUMX. zatian, seccomp Kubernetes-en inplementatzeko oinarriak eta barne xehetasunak azalduko ditut.

Kubernetes ekosistemak ontziak babesteko eta isolatzeko modu ugari eskaintzen ditu. Artikulua Secure Computing Moderi buruzkoa da, izenez ere ezaguna seccomp. Bere funtsa exekutatzeko dauden sistema-deiak edukiontzien bidez iragaztea da.

Zergatik da garrantzitsua? Edukiontzi bat makina zehatz batean exekutatzen den prozesu bat besterik ez da. Eta nukleoa beste aplikazio batzuek bezala erabiltzen du. Edukiontziek sistema-deiren bat egin ahal izango balute, oso laster malware-ek aprobetxatuko luke edukiontzien isolamendua saihesteko eta beste aplikazio batzuei eragiten: informazioa atzemateko, sistemaren ezarpenak aldatzeko, etab.

seccomp profilek definitzen dute zein sistema-deiak onartu edo desgaitu behar diren. Edukiontziaren exekuzio-denborak abiarazten ditu abiaraztean, nukleoak haien exekuzioa kontrolatu dezan. Horrelako profilak erabiltzeak eraso-bektorea mugatu eta kalteak murrizteko aukera ematen du edukiontziaren barruan dagoen edozein programa (hau da, zure menpekotasunak edo haien menpekotasunak) baimenik ez duen zerbait egiten hasten bada.

Oinarrietara iristea

Oinarrizko seccomp profilak hiru elementu ditu: defaultAction, architectures (Edo archMap) Eta syscalls:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "sched_yield",
                "futex",
                "write",
                "mmap",
                "exit_group",
                "madvise",
                "rt_sigprocmask",
                "getpid",
                "gettid",
                "tgkill",
                "rt_sigaction",
                "read",
                "getpgrp"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

(medium-basic-seccomp.json)

defaultAction atalean zehaztu gabeko sistema-deien lehenetsitako patua zehazten du syscalls. Gauzak errazteko, zentratu gaitezen erabiliko diren bi balio nagusietan:

  • SCMP_ACT_ERRNO - sistema dei baten exekuzioa blokeatzen du,
  • SCMP_ACT_ALLOW - ahalbidetzen du.

Atalean architectures xede-arkitekturak zerrendatzen dira. Garrantzitsua da iragazkia bera, nukleo mailan aplikatuta, sistema-deien identifikatzaileen araberakoa delako, eta ez profilean zehaztutako izenen arabera. Edukiontziaren exekuzio-denborak identifikatzaileekin bat egingo du erabili aurretik. Ideia da sistema-deiek ID guztiz desberdinak izan ditzaketela sistema-arkitekturaren arabera. Adibidez, sistema deia recvfrom (socketetik informazioa jasotzeko erabiltzen da) ID = 64 x64 sistemetan eta ID = 517 x86-n. Hemen x86-x64 arkitekturaren sistema-dei guztien zerrenda aurki dezakezu.

atalean syscalls sistema dei guztiak zerrendatzen ditu eta haiekin zer egin zehazten du. Adibidez, zerrenda zuri bat sor dezakezu ezarriz defaultAction on SCMP_ACT_ERRNO, eta deiak atalean syscalls esleitu SCMP_ACT_ALLOW. Horrela, atalean zehaztutako deiak bakarrik onartzen dituzu syscalls, eta gainontzeko guztiak debekatu. Zerrenda beltzeko balioak aldatu behar dituzu defaultAction eta kontrako ekintzak.

Orain hain agerikoak ez diren ñabardurei buruz hitz batzuk esan beharko genituzke. Kontuan izan beheko gomendioek Kubernetes-en negozio-aplikazio-lerro bat zabaltzen ari zarela suposatzen dutela eta ahalik eta pribilegio gutxienekin exekutatu nahi dituzula.

1. AllowPrivilegeEscalation=faltsua

В securityContext edukiontziak parametro bat du AllowPrivilegeEscalation. Bertan instalatuta badago false, edukiontziak (on) bit no_new_priv. Parametro honen esanahia agerikoa da izenetik: edukiontziak berak baino pribilegio gehiago dituzten prozesu berriak abiaraztea eragozten du.

Ezarritako aukera honen bigarren mailako efektua true (lehenetsia) edukiontziaren exekuzio-denborak seccomp profila abiarazteko prozesuaren hasieran aplikatzen duela da. Horrela, barne exekuzio-denborako prozesuak exekutatzeko beharrezkoak diren sistema-dei guztiak (adibidez, erabiltzaile/talde IDak ezartzea, gaitasun batzuk kentzea) gaituta egon behar dute profilean.

Gauza hutsalak egiten dituen edukiontzi batera echo hi, baimen hauek beharko dira:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "brk",
                "capget",
                "capset",
                "chdir",
                "close",
                "execve",
                "exit_group",
                "fstat",
                "fstatfs",
                "futex",
                "getdents64",
                "getppid",
                "lstat",
                "mprotect",
                "nanosleep",
                "newfstatat",
                "openat",
                "prctl",
                "read",
                "rt_sigaction",
                "statfs",
                "setgid",
                "setgroups",
                "setuid",
                "stat",
                "uname",
                "write"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

(hi-pod-seccomp.json)

... hauen ordez:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "brk",
                "close",
                "execve",
                "exit_group",
                "futex",
                "mprotect",
                "nanosleep",
                "stat",
                "write"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

(hi-container-seccomp.json)

Baina berriro, zergatik da arazo hau? Pertsonalki, sistema-dei hauek zerrenda zurian jartzea saihestuko nuke (benetako beharrik ez badago behintzat): capset, set_tid_address, setgid, setgroups и setuid. Hala ere, benetako erronka da inolako kontrolik ez dituzun prozesuak baimenduz, profilak edukiontzien exekuzio-denboran inplementazioari lotzen ari zarela. Beste era batera esanda, baliteke egunen batean edukiontzien exekuzio-ingurunea eguneratu ondoren (zuk edo, seguruenik, hodeiko zerbitzu-hornitzaileak), edukiontziak bat-batean exekutatzen utziko duela.

1. aholkua: Exekutatu edukiontziak AllowPrivilegeEscaltion=false. Honek seccomp profilen tamaina murriztuko du eta edukiontzien exekuzio-ingurunean izandako aldaketekiko sentikorrak izango dira.

2. Edukiontzi mailan seccomp profilak ezartzea

Seccomp profila pod mailan ezar daiteke:

annotations:
  seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"

...edo edukiontzi mailan:

annotations:
  container.security.alpha.kubernetes.io/<container-name>: "localhost/profile.json"

Kontuan izan goiko sintaxia aldatu egingo dela Kubernetes seccomp denean GA bihurtuko da (Gertaera hau Kubernetes-en hurrengo bertsioan espero da - 1.18 - gutxi gorabehera itzulpena).

Inor gutxik daki Kubernetesek beti izan duela akatsahorrek seccomp profilak aplikatzea eragin zuen pausa edukiontzia. Exekuzio-inguruneak partzialki konpentsatzen du gabezia hori, baina edukiontzi hau ez da leketatik desagertzen, haien azpiegitura konfiguratzeko erabiltzen baita.

Arazoa da edukiontzi hau beti hasten dela AllowPrivilegeEscalation=true, 1. paragrafoan adierazitako arazoak ekarriz, eta hori ezin da aldatu.

Edukiontzi mailan seccomp profilak erabiliz, hutsune hori saihesten duzu eta edukiontzi jakin bati egokitutako profila sor dezakezu. Hori egin beharko da garatzaileek akatsa konpondu eta bertsio berria (1.18 agian?) guztion eskura egon arte.

2. aholkua: Ezarri seccomp profilak edukiontzi mailan.

Zentzu praktikoan, arau honek galderari erantzun unibertsal gisa balio ohi du: "Zergatik funtzionatzen du nire seccomp profilak? docker runbaina ez al du funtzionatzen Kubernetes kluster batean zabaldu ondoren?

3. Erabili exekuzio-denbora/lehenetsia azken aukera gisa soilik

Kubernetes-ek bi aukera ditu integratutako profiletarako: runtime/default и docker/default. Biak edukiontzien exekuzio-denborak inplementatzen ditu, ez Kubernetes. Beraz, erabilitako exekuzio-ingurunearen eta bere bertsioaren arabera desberdinak izan daitezke.

Beste era batera esanda, exekuzio-denbora aldatzearen ondorioz, edukiontziak beste sistema-deien multzo baterako sarbidea izan dezake, erabil ditzake edo ez. Exekuzio-denbora gehienek erabiltzen dute Docker ezarpena. Profil hau erabili nahi baduzu, ziurtatu zuretzako egokia dela.

Profile docker/default Kubernetes 1.11etik zaharkituta dago, beraz, saihestu hura erabiltzea.

Nire ustez, profila runtime/default sortu zen helbururako guztiz egokia da: erabiltzaileak komando bat exekutatzeak lotutako arriskuetatik babestea docker run beren autoetan. Hala ere, Kubernetes klusterretan exekutatzen diren negozio-aplikazioei dagokienez, ausartuko nintzateke esatera profil hori irekiegia dela eta garatzaileek beren aplikazioetarako (edo aplikazio motetarako) profilak sortzean zentratu beharko luketela.

3. aholkua: Sortu seccomp profilak aplikazio zehatzetarako. Hori ezinezkoa bada, sortu aplikazio moten profilak, adibidez, sortu Golang aplikazioaren web API guztiak biltzen dituen profil aurreratu bat. Erabili exekuzio-denbora/lehenetsia soilik azken aukera gisa.

Etorkizuneko argitalpenetan, SecDevOps-en inspiratutako seccomp profilak nola sortu, automatizatu eta kanalizazioetan nola probatu azalduko dut. Beste era batera esanda, ez duzu aitzakiarik izango aplikazioaren profil espezifikoetara ez berritzeko.

4. Unconfined EZ da aukera bat.

Of Kubernetesen lehen segurtasun auditoria hori lehenespenez atera zen seccomp desgaituta. Horrek esan nahi du ez baduzu ezartzen PodSecurityPolicy, eta horrek klusterrean gaituko du, seccomp profila definitu ez den pod guztiek funtzionatuko dute seccomp=unconfined.

Modu honetan funtzionatzeak esan nahi du kluster babesten duen isolamendu-geruza osoa galtzen dela. Ikuspegi hau ez dute gomendatzen segurtasun adituek.

4. aholkua: Klusterreko edukiontzirik ez luke martxan egon behar seccomp=unconfined, batez ere ekoizpen inguruneetan.

5. "Ikuskaritza modua"

Puntu hau ez da Kubernetesen bakarra, baina oraindik "hasi aurretik jakin beharreko gauzak" kategorian sartzen da.

Gertatzen den bezala, seccomp profilak sortzea beti izan da erronka eta saiakuntzan eta akatsetan oinarritzen da. Kontua da erabiltzaileek ez dutela produkzio-inguruneetan probatzeko aukerarik aplikazioa "erortzeko" arriskurik gabe.

Linux kernel 4.14 kaleratu ondoren, profil baten zatiak auditoria moduan exekutatu ahal izan ziren, sistema-dei guztiei buruzko informazioa syslog-en erregistratuz, baina blokeatu gabe. Modu hau parametroa erabiliz aktibatu dezakezu SCMT_ACT_LOG:

SCMP_ACT_LOG: seccomp-ek ez dio eragingo sistema-deia egiten duen harian iragazkien araurik bat ez badator, baina sistema-deiari buruzko informazioa erregistratuko da.

Hona hemen funtzio hau erabiltzeko ohiko estrategia:

  1. Baimendu behar diren sistema-deiak.
  2. Dakizuen sistematik blokeatu deiak ez direla erabilgarriak izango.
  3. Grabatu beste dei guztiei buruzko informazioa erregistroan.

Adibide sinplifikatu batek itxura hau du:

{
    "defaultAction": "SCMP_ACT_LOG",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "arch_prctl",
                "sched_yield",
                "futex",
                "write",
                "mmap",
                "exit_group",
                "madvise",
                "rt_sigprocmask",
                "getpid",
                "gettid",
                "tgkill",
                "rt_sigaction",
                "read",
                "getpgrp"
            ],
            "action": "SCMP_ACT_ALLOW"
        },
        {
            "names": [
                "add_key",
                "keyctl",
                "ptrace"
            ],
            "action": "SCMP_ACT_ERRNO"
        }
    ]
}

(ertain-mixed-seccomp.json)

Baina gogoratu erabiliko ez direla dakizun dei guztiak blokeatu behar dituzula eta klusterari kalte egin diezaioketela. Zerrenda bat osatzeko oinarri ona ofiziala da Docker dokumentazioa. Xehetasunez azaltzen du zein sistema-deiak blokeatzen diren profil lehenetsian eta zergatik.

Hala ere, bada harrapaketa bat. Nahiz eta SCMT_ACT_LOG Linux kernelak onartzen duen 2017 amaieratik, Kubernetes ekosisteman duela gutxi sartu zen. Hori dela eta, metodo hau erabiltzeko Linux kernel 4.14 eta runC bertsio txikiagoa beharko duzu v1.0.0-rc9.

5. aholkua: Ekoizpenean probak egiteko auditoria moduko profil bat sor daiteke zerrenda zuriak eta beltzak konbinatuz, eta salbuespen guztiak erregistratu daitezke.

6. Erabili zerrenda zuriak

Zerrenda zuriak esfortzu gehigarria eskatzen du, aplikazioak behar ditzakeen dei guztiak identifikatu behar dituzulako, baina ikuspegi honek segurtasuna asko hobetzen du:

Oso gomendagarria da zerrenda zuriaren ikuspegia erabiltzea sinpleagoa eta fidagarriagoa baita. Zerrenda beltza eguneratu beharko da arriskutsua izan daitekeen sistema-dei bat gehitzen den bakoitzean (edo bandera/aukera arriskutsu bat zerrenda beltzean badago). Horrez gain, sarritan posible da parametro baten irudikapena aldatzea bere funtsa aldatu gabe eta, ondorioz, zerrenda beltzaren murrizketak saihestu.

Go aplikazioetarako, aplikazioarekin batera doan eta exekuzioan egindako dei guztiak biltzen dituen tresna berezi bat garatu dut. Adibidez, aplikazio honetarako:

package main

import "fmt"

func main() {
	fmt.Println("test")
}

... martxan gaitezen gosystract hau:

go install https://github.com/pjbgf/gosystract
gosystract --template='{{- range . }}{{printf ""%s",n" .Name}}{{- end}}' application-path

... eta emaitza hau lortzen dugu:

"sched_yield",
"futex",
"write",
"mmap",
"exit_group",
"madvise",
"rt_sigprocmask",
"getpid",
"gettid",
"tgkill",
"rt_sigaction",
"read",
"getpgrp",
"arch_prctl",

Oraingoz, hau adibide bat besterik ez da; ondoren, tresnei buruzko xehetasun gehiago egongo dira.

6. aholkua: onartu benetan behar dituzun deiak soilik eta blokeatu gainerako guztiak.

7. Jarri oinarri egokiak (edo prestatu ustekabeko portaerarako)

Nukleoak profila betearaziko du bertan idazten duzuna kontuan hartu gabe. Nahiz eta nahi zenuena ez izan. Adibidez, bezalako deien sarbidea blokeatzen baduzu exit edo exit_group, edukiontzia ezin izango da behar bezala itzali eta baita komando sinple bat ere echo hi zintzilikatu hurao epe mugagaberako. Ondorioz, CPU erabilera handia lortuko duzu klusterrean:

Seccomp Kubernetes-en: hasiera-hasieratik jakin behar dituzun 7 gauza

Kasu horietan, erabilgarritasun bat etor daiteke erreskatatzera strace - Arazoa zein izan daitekeen erakutsiko du:

Seccomp Kubernetes-en: hasiera-hasieratik jakin behar dituzun 7 gauza
sudo strace -c -p 9331

Ziurtatu profilek aplikazioak exekuzioan behar dituen sistema-dei guztiak dituela.

7. aholkua: Erreparatu xehetasunei eta ziurtatu beharrezko sistema-dei guztiak zerrenda zurian daudela.

Honekin amaitzen da Kubernetes-en seccomp erabiltzeari buruzko artikulu sortaren lehen zatia SecDevOps-en izpirituan. Ondorengo zatietan hau zergatik den garrantzitsua eta prozesua nola automatizatu azalduko dugu.

PS itzultzailetik

Irakurri ere gure blogean:

Iturria: www.habr.com

Gehitu iruzkin berria