Seccomp Kubernetesis: 7 asja, mida alates algusest alustada

Märk. tõlge.: Esitame tõlke Briti ettevõtte ASOS.com vanema rakenduste turvainseneri artiklist. Sellega alustab ta veebisarja, mis on pühendatud Kuberneteseteabe turvalisuse tõstmisele seccompi kasutamise kaudu. Kui sissetoomine meeldib lugejatele, järgime autorit ja jätkame tema tulevaste materjalidega sellel teemal.

Seccomp Kubernetesis: 7 asja, mida alates algusest alustada

See artikkel on esimene osa sarjast, mis käsitleb seccompi profiilide loomist SecDevOps vaimus, vältides samas maagia ja nõiduse kasutamist. Esimeses osas räägin seccompi põhialustest ja sisemistest detailidest Kubernetesis.

Kubernetesi ökosüsteem pakub piisavalt erinevaid viise konteinerite turvamiseks ja isoleerimiseks. Artikkel on pühendatud Secure Computing Mode'ile, mida tuntakse ka kui , ja palju muud.. Selle olemus seisneb süsteemi kõnede filtreerimises, millele konteinerid on juurdepääsuga.

Miks see oluline on? Konteiner on lihtsalt protsess, mis on käivitatud kindlas masinas. Ja ta kasutab tuuma koos teiste rakendustega. Kui konteinerid saaksid teha igasuguseid süsteemikõnesid, kasutaksid seda peagi pahatahtlikud programmid, et mööda minna konteineri isolatsioonist ja mõjutada teisi rakendusi: teavet pealt kuulata, süsteemi seadeid muutma jne.

Seccomp'i profilid määravad, millised süsteemikõned peavad olema lubatud või keelatud. Konteineri töökeskkond aktiveerib need selle käivitamisel, et tuum saaks jälgida nende täitmist. Selliste profiilide rakendamine võimaldab piirata rünnakueesmärke ja vähendada kahju, juhul kui mõni programm konteineri sees (st teie sõltuvused või nende sõltuvused) hakkab tegema seda, mida tal lubatud ei ole.

Alustame põhialustega

Seccomp'i põhiprofiil sisaldab kolme elementi: defaultAction, architectures (või archMap) ja 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 määrab vaikeväärtuse mis tahes süsteemikõne puhul, mis ei ole loetletud syscalls. Ülesande lihtsustamiseks keskendume kahele peamisele tähendusele, mida hakatakse kasutama:

  • SCMP_ACT_ERRNO — blokeerib süsteemikõne täitmise,
  • SCMP_ACT_ALLOW — lubab.

Jaotises architectures loetletakse sihtarhitektuurid. See on oluline, kuna filter, mida rakendatakse tuumatasemel, sõltub süsteemikõnede identifikaatoritest, mitte nende nimedest, mis on määratud profiilis. Enne rakendamist vastab konteineri käituskeskkond need identifikaatoritega. Idee on selles, et süsteemikõned võivad oleneda süsteemi arhitektuurist, omades täiesti erinevaid ID-sid. Näiteks süsteemikõne recvfrom kasutatakse teabe saamiseks socket'ilt) omab ID = 64 x64 süsteemides ja ID = 517 x86. Siit leiate leida loetelu kõikidest süsteemikõnedest x86-x64 arhitektuuride jaoks.

jaotises syscalls loetletakse kõik süsteemikõned ja antakse teada, mida nendega teha. Näiteks saab luua valge nimekirja, seadistades defaultAction järgnevaga SCMP_ACT_ERRNO, ning kõnedele sektsioonis syscalls anda SCMP_ACT_ALLOW. Nii lubate ainult sektsioonis loetletud kõned ja keeldate kõik ülejäänud. Musta nimekirja jaoks tuleks vahetada väärtused syscallsja tegevused vastupidiseks. defaultAction Nüüd tasub öelda paar sõna nüanssidest, mis ei ole nii ilmsed. Pange tähele, et allpool olevad soovitused tulenevad sellest, et te arendate Kuberneteses ärirakenduste seeriat ja teile on oluline, et need töötaksid vähimate privileegidega.

1. AllowPrivilegeEscalation=false

konteineri jaoks on olemas parameeter

V securityContext AllowPrivilegeEscalation . Kui see on seadistatud, käivitatakse konteinerid seatud ( false) bitigaonno_new_priv . Selle parameetri tähendus on selle nimest selge: see ei luba konteineril käivitada uusi protsesse privileegidega, mis on kõrgemad kui tal endal on.Selle parameetri seadmine

Побочным эффектом этого параметра, установленного в true (vaikeväärtus) on see, et konteineri runtime rakendab seccomp profiili protsessi käivitamise alguses. Seega peavad kõik süsteemi kutsed, mis on vajalikud jooksva keskkonna sisemistest protsessidest (näiteks kasutaja/grupi ID-de seadmine, teatud õiguste mahalangetamine), profiilis lubatud olema.

Konteiner, mis käivitab lihtsa echo hi, vajab järgmisi õigusi:

{
    "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)

… nende asemel:

{
    "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)

Aga jälle, miks see probleem on? Isiklikult vältin ma järgmiste süsteemikõnede lisamist valgesse nimekirja (kui see pole tõeliselt vajalik): capset, set_tid_address, setgid, setgroups ja setuid. Siiski seisneb tõeline keerukus selles, et lubades protsesse, mida te absoluutselt ei kontrolli, seote te profiilid konteineri töökeskkonna rakendusega. Teisisõnu, võite ühel hetkel avastada, et pärast konteineri töökeskkonna värskendamist (teie või tõenäolisemalt pilveteenuse pakkuja poolt) lakuvad konteinerid äkitselt töötamast.

Nõuanne nr 1: Käivitage konteinerid koos AllowPrivilegeEscaltion=false. See vähendab seccomp-profiilide suurust ja muudab need konteineri töökeskkonna muutustele vähem tundlikeks.

2. Seccomp-profiilide seadmine konteineri tasemel

Seccomp-profiili saab määrata pod'i tasemel:

märgid:
  seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"

… või konteineri tasandil:

märgid:
  container.security.alpha.kubernetes.io/<konteineri-nimi>: "localhost/profile.json"

Pange tähele, et ülaltoodud süntaks muutub, kui Kubernetes seccomp saab GA-ks (see sündmus on oodata juba järgmises Kubernetes’i versioonis — 1.18 — tõlkija märkus).

Kuid vähesed teavad, et Kubernetes’is on alati olnud viga, mille tõttu seccomp profiile rakendati pause-konteinerile. Käituskeskkond kompenseerib osaliselt seda puudust, kuid see konteiner ei kao pod'idest kuhugi, kuna seda kasutatakse nende infrastruktuuri seadistamiseks.

Küsimus on aga selles, et see konteiner käivitatakse alati AllowPrivilegeEscalation=true, mis toob kaasa punktis 1 välja toodud probleemid, ja seda ei saa muuta.

Rakendades seccomp profiile konteineri tasandil, vältite seda lõksu ja saate luua profiili, mis on "kohandatud" konkreetse konteineri jaoks. Nii tuleb teha seni, kuni arendajad vea parandavad ja uus versioon (võib-olla 1.18?) on kõigile huvilistele saadaval.

Nõuanne nr 2: Määrake seccomp profiilid konteineri tasandil.

Praktilises mõttes on see reegel tavaliselt universaalne vastus küsimusele: „Miks minu seccomp-profiil töötab, kuid ei tööta pärast Kubernetese klastrisse juurutamist?" docker run, но не работает после развертывания в кластере Kubernetes?».

3. Kasuta runtime/default vaid äärmise vajaduse korral

Kuberneteses on kaks sisseehitatud profiili: runtime/default ja docker/default. Mõlemad rakendatakse konteineri käituskeskkonna, mitte Kubernetese poolt. Seetõttu võivad need varieeruda sõltuvalt kasutatavast käituskeskkonnast ja selle versioonist.

Teisisõnu, konteineri käituskeskkonna muutumise tulemusena võib konteiner pääseda ligi teistsugusele süsteemi kutsumise kogumile, mida ta võib kasutada või mitte. Enamik käituskeskkondi kasutab Docker'i rakendust. Kui soovid seda profiili kasutada, veendu, et see sobib sulle.

Profiil docker/default on alates Kubernetes 1.11 välja arvatud, seega vältige selle kasutamist.

Minu arvates on profiil runtime/default ideaalselt sobiv selleks, milleks see loodi: kasutajate kaitsmiseks käskude täitmisega seotud riskide eest. docker run Kuitenki, rääkides Kubernetes'i klastrites töötavatest ärrakendustest, julgen öelda, et selline profiil on liiga avatud ja arendajad peaksid keskenduma oma rakendustele (või rakenduste tüüpidele) sobivate profiilide loomisele.

Nõuanne №3: Looge seccomp profiile konkreetsete rakenduste jaoks. Kui see ei ole võimalik, tegelege rakendustüüpide profiilidega, näiteks looge laiendatud profiil, mis hõlmab kõiki Golangi rakenduse veeb-API-sid. Kasutage runtime/default'i ainult viimase abinõuna.

Tulevastes postitustes räägin, kuidas luua seccomp profiile SecDevOps'i vaimus, automatiseerida ja testida neid töövoogudes. Teisisõnu, teil ei jää enam vabandusi, et mitte liikuda konkreetsete rakenduste profiilide kasutamisele.

4. Unconfined — see EI OLE valik

Uusimad esimese Kubernetes'i turbeauditi käigus selgus, et vaikimisi seccomp on keelatud. See tähendab, et kui te ei seadista PodSecurityPolicy, mis võimaldab seda klastris, töötavad kõik pod'id, mille jaoks ei ole seccomp profiili määratud, režiimis seccomp=unconfined.

Sellise režiimi kasutamine tähendab, et kaob terve isolatsiooni kiht, mis kaitseb klastreid. Sellist lähenemist ei soovita turbeeksperdid.

Nõuanne nr 4: Ükski konteiner klastris ei tohiks töötada režiimis seccomp=unconfined, eriti tootmiskeskkondades.

5. "Auditirežiim"

See punkt ei ole unikaalne Kubernetes'e jaoks, kuid kuulub siiski kategooriasse "mille üle tasub juba enne alustamist mõelda."

On teada, et seccomp profiilide loomine on alati olnud keeruline ja põhinenud suuresti katse-eksituse meetodil. Asi on selles, et kasutajatel ei ole lihtsalt võimalust neid tootmiskeskkondades testida, ilma et nad riskiksid rakenduse "maha kukutamise."

Pärast Linuxi tuuma 4.14 ilmumist on võimalik käivitada profiili osasid auditirežiimis, salvestades syslog'i kõikide süsteemikõnede kohta teavet, kuid neid mitte blokeerides. Selle režiimi aktiveerimiseks saab kasutada parameetrit SCMT_ACT_LOG:

SCMP_ACT_LOG: seccomp ei avalda mõju süsteemikõnet tegeva protsessi tööle, kui see ei allu ühele rikke reeglist, kuid teave süsteemikõne kohta kantakse logisse.

Siin on tüüpiline strateegia selle võimaluse kasutamiseks:

  1. Luba süsteemi kutseid, mis on vajalikud.
  2. Blokeeri süsteemi kutsed, mille ei ole teada, et need oleksid vajalikud.
  3. Kõikide teiste kutsete kohta teabe logimine.

Lihtne näide näeb välja järgmine:

{
    "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"
        }
    ]
}

(medium-mixed-seccomp.json)

Aga pidage meeles, et tuleb blokeerida kõik kutsed, mille osas on teada, et neid ei kasutata ja mis võivad potentsiaalselt klastrile kahju teha. Hea alus nimekirja koostamiseks on ametlik Docker dokumentatsioon. See seletab üksikasjalikult, millised süsteemi kutseid on vaikeprofiilis blokeeritud ja miks.

Siiski on üks peenem koht. Kuigi SCMT_ACT_LOG Linuxi tuuma toetatakse alates 2017. aasta lõpust, siis on see Kubernetes'i ökosüsteemi jõudnud alles hiljuti. Seetõttu on selle meetodi kasutamiseks vajalik Linuxi tuum versioon 4.14 ja runC versioon mitte madalam kui v1.0.0-rc9.

Nõuanne nr 5: Auditi režiimi profiili loomine tootmisjärgus võib toimuda mustade ja valgete nimede kombinatsiooni kaudu, salvestades kõik erandid logisse.

6. Kasutage valgeid nimesid

Valgete nimede koostamine nõuab lisatööd, kuna tuleb tuvastada iga koodikutsumine, mida rakendus vajada võiks, kuid see meetod suurendab oluliselt turvalisust:

Soovitatav on kasutada valgete nimede lähenemist, kuna see on lihtsam ja usaldusväärsem. Musta nimekirja tuleb iga kord värskendada potentsiaalselt ohtliku süsteemikutsumise (või ohtliku lipu/valiku puhul, kui need on mustas nimekirjas) lisamisel. Lisaks on sageli võimalik muuta argumentide esitust, säilitades samas nende sisu ja seeläbi vältida musta nimekirja piiranguid.

Go keeles rakenduste jaoks olen välja töötanud spetsiaalse tööriista, mis jälgib rakendust ja kogub kõik käikud, mis toimusid käitamise ajal. Näiteks järgmise rakenduse jaoks:

package main

import "fmt"

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

… käivitame gosystract nii:

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

… ja saame järgmise tulemuse:

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

Praegu on see vaid näide — tööriistade kohta on rohkem üksikasju hiljem.

Nõuanne №6: Lubage ainult need kutset, mis on teile tõeliselt vajalikud, ja blokeerige kõik ülejäänud.

7. Looge õiged alused (või valmistuge ettearvamatuks käitumiseks)

Tuuma jälgib teie määratud profiili sõltumata sellest, mida olete sinna kirjutanud. Isegi kui see pole päris see, mida soovisite. Näiteks, kui blokeerida juurdepääs kutsetele nagu exit või exit_group, ei suuda konteiner korralikult lõpetada, ja isegi lihtne käsk echo hi jätab sellemääramatuks ajaks. Tulemuseks on kõrge CPU koormus klastris:

Seccomp Kubernetesis: 7 asja, mida alates algusest alustada

Nendel juhtudel võib abiks olla utiliit strace — ta näitab, milles probleem võib seisneda:

Seccomp Kubernetesis: 7 asja, mida alates algusest alustada
sudo strace -c -p 9331

Veenduge, et profiilid sisaldavad kõiki süsteemi kõnesid, mida rakendus vajab töö ajal.

Nõuanne #7: Olge detailide suhtes ettevaatlikud ja kontrollige, et kõik vajalikud süsteemi kõned on lubatud.

Selle artiklite seeria esimene osa seccomp'i kasutamisest Kuberneteses SecDevOps vaimus jõuab lõpule. Järgnevates osades räägime, miks see on oluline ja kuidas protsessi automatiseerida.

P.S. tõlkija märkused

Lugege ka meie blogist:

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster