Seccomp in Kubernetes: 7 lietas, kas jums jāzina no paŔa sākuma

PiezÄ«me. tulk.: JÅ«su uzmanÄ«bai piedāvājam Lielbritānijas uzņēmuma ASOS.com vecākā lietojumprogrammu droŔības inženiera raksta tulkojumu. Ar to viņŔ sāk publikāciju sēriju, kas veltÄ«ta Kubernetes droŔības uzlaboÅ”anai, izmantojot seccomp. Ja lasÄ«tājiem patiks ievads, mēs sekosim autoram un turpināsim ar viņa turpmākajiem materiāliem par Å”o tēmu.

Seccomp in Kubernetes: 7 lietas, kas jums jāzina no paŔa sākuma

Å is raksts ir pirmais no ziņu sērijas par to, kā izveidot seccomp profilus SecDevOps garā, neizmantojot maÄ£iju un burvestÄ«bas. XNUMX. daļā es apskatÄ«Å”u pamatus un iekŔējo informāciju par seccomp ievieÅ”anu Kubernetes.

Kubernetes ekosistēma piedāvā dažādus veidus, kā nostiprināt un izolēt konteinerus. Raksts ir par droÅ”o skaitļoÅ”anas režīmu, kas pazÄ«stams arÄ« kā seccomp. Tās bÅ«tÄ«ba ir filtrēt izpildei pieejamos sistēmas zvanus pēc konteineriem.

Kāpēc tas ir svarÄ«gi? Konteiners ir tikai process, kas darbojas noteiktā maŔīnā. Un tas izmanto kodolu tāpat kā citas lietojumprogrammas. Ja konteineri varētu veikt jebkādus sistēmas izsaukumus, ļoti drÄ«z ļaunprātÄ«ga programmatÅ«ra to izmantotu, lai apietu konteineru izolāciju un ietekmētu citas lietojumprogrammas: pārtvertu informāciju, mainÄ«tu sistēmas iestatÄ«jumus utt.

seccomp profili nosaka, kuri sistēmas izsaukumi ir jāatļauj vai jāatspējo. Konteinera izpildlaiks tos aktivizē, kad tas sākas, lai kodols varētu pārraudzÄ«t to izpildi. Izmantojot Ŕādus profilus, varat ierobežot uzbrukuma vektoru un samazināt bojājumus, ja kāda programma konteinerā (tas ir, jÅ«su atkarÄ«bas vai to atkarÄ«bas) sāk darÄ«t kaut ko tādu, kas tai nav atļauts.

Pamatu izpratne

Pamata seccomp profils ietver trīs elementus: defaultAction, architectures (Vai archMap) Un 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 nosaka jebkura sistēmas izsaukuma noklusējuma likteni, kas nav norādīts sadaļā syscalls. Lai lietas būtu vieglākas, pievērsīsimies divām galvenajām vērtībām, kas tiks izmantotas:

  • SCMP_ACT_ERRNO ā€” bloķē sistēmas izsaukuma izpildi,
  • SCMP_ACT_ALLOW - ļauj.

Iedaļā architectures ir norādÄ«tas mērÄ·a arhitektÅ«ras. Tas ir svarÄ«gi, jo pats filtrs, kas tiek lietots kodola lÄ«menÄ«, ir atkarÄ«gs no sistēmas izsaukuma identifikatoriem, nevis no profilā norādÄ«tajiem to nosaukumiem. Pirms lietoÅ”anas konteinera izpildlaiks tos saskaņos ar identifikatoriem. Ideja ir tāda, ka sistēmas zvaniem var bÅ«t pilnÄ«gi atŔķirÄ«gi ID atkarÄ«bā no sistēmas arhitektÅ«ras. Piemēram, sistēmas izsaukums recvfrom (izmanto, lai saņemtu informāciju no ligzdas) ir ID = 64 x64 sistēmās un ID = 517 x86. Å eit jÅ«s varat atrast sarakstu ar visiem sistēmas izsaukumiem x86-x64 arhitektÅ«rām.

Sadaļā syscalls uzskaita visus sistēmas zvanus un norāda, ko ar tiem darÄ«t. Piemēram, iestatot, varat izveidot balto sarakstu defaultAction par SCMP_ACT_ERRNO, un zvani sadaļā syscalls pieŔķirt SCMP_ACT_ALLOW. Tādējādi jÅ«s atļaujat tikai sadaļā norādÄ«tos zvanus syscalls, un aizliegt visus citus. Melnajā sarakstā ir jāmaina vērtÄ«bas defaultAction un darbÄ«bas uz pretējo.

Tagad mums vajadzētu teikt dažus vārdus par niansēm, kas nav tik acīmredzamas. Lūdzu, ņemiet vērā, ka tālāk sniegtajos ieteikumos tiek pieņemts, ka vietnē Kubernetes izvietojat biznesa lietojumprogrammu līniju un vēlaties, lai tās darbotos ar iespējami mazākām privilēģijām.

1. AllowPrivilegeEscalation=false

Š’ securityContext konteineram ir parametrs AllowPrivilegeEscalation. Ja tas ir instalēts false, konteineri sāksies ar (on) mazliet no_new_priv. Å Ä« parametra nozÄ«me ir acÄ«mredzama no nosaukuma: tas neļauj konteineram palaist jaunus procesus ar vairāk privilēģijām, nekā tas pats ir.

Å Ä«s opcijas iestatÄ«Å”anas blakusefekts true (noklusējums) ir tas, ka konteinera izpildlaiks lieto seccomp profilu startÄ“Å”anas procesa paŔā sākumā. Tādējādi profilā ir jāiespējo visi sistēmas izsaukumi, kas nepiecieÅ”ami iekŔējo izpildlaika procesu palaiÅ”anai (piemēram, lietotāja/grupas ID iestatÄ«Å”ana, noteiktu iespēju atmeÅ”ana).

Uz konteineru, kas dara sīkas lietas echo hi, būs nepiecieŔamas Ŕādas atļaujas:

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

...Ŕo vietā:

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

Bet atkal, kāpēc tā ir problēma? PersonÄ«gi es izvairÄ«tos no Ŕādu sistēmas izsaukumu iekļauÅ”anas baltajā sarakstā (ja vien tie nav reālas vajadzÄ«bas): capset, set_tid_address, setgid, setgroups Šø setuid. Tomēr patiesais izaicinājums ir tāds, ka, atļaujot procesus, kurus jÅ«s absolÅ«ti nevarat kontrolēt, jÅ«s saistāt profilus ar konteinera izpildlaika ievieÅ”anu. Citiem vārdiem sakot, kādu dienu jÅ«s varat atklāt, ka pēc konteinera izpildlaika vides atjaunināŔanas (jÅ«s vai, visticamāk, mākoņpakalpojuma sniedzējs), konteineri pēkŔņi pārstāj darboties.

Padoms # 1: Palaist konteinerus ar AllowPrivilegeEscaltion=false. Tas samazinās seccomp profilu lielumu un padarīs tos mazāk jutīgus pret izmaiņām konteinera izpildlaika vidē.

2. Seccomp profilu iestatīŔana konteinera līmenī

seccomp profilu var iestatīt pod līmenī:

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

...vai konteinera līmenī:

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

LÅ«dzu, ņemiet vērā, ka iepriekÅ” minētā sintakse mainÄ«sies, kad Kubernetes seccomp kļūs par GA (Å”is notikums gaidāms nākamajā Kubernetes izlaidumā - 1.18 - apm. tulk.).

Tikai daži cilvēki zina, ka Kubernetes vienmēr ir bijis kļūdakas izraisÄ«ja seccomp profilu lietoÅ”anu pauzes konteiners. Izpildlaika vide daļēji kompensē Å”o trÅ«kumu, taču Å”is konteiners nepazÅ«d no podiem, jo ā€‹ā€‹tiek izmantots to infrastruktÅ«ras konfigurÄ“Å”anai.

Problēma ir tā, ka Å”is konteiners vienmēr sākas ar AllowPrivilegeEscalation=true, kas rada 1. punktā minētās problēmas, un to nevar mainÄ«t.

Izmantojot seccomp profilus konteinera lÄ«menÄ«, jÅ«s izvairÄ«sities no Ŕīs kļūmes un varat izveidot profilu, kas ir pielāgots konkrētam konteineram. Tas bÅ«s jādara, lÄ«dz izstrādātāji novērsÄ«s kļūdu un jaunā versija (varbÅ«t 1.18?) kļūs pieejama visiem.

Padoms # 2: iestatiet seccomp profilus konteinera līmenī.

Praktiskā nozÄ«mē Å”is noteikums parasti kalpo kā universāla atbilde uz jautājumu: ā€œKāpēc mans seccomp profils darbojas ar docker runbet nedarbojas pēc izvietoÅ”anas Kubernetes klasterÄ«?

3. Izmantojiet izpildlaiku/noklusējumu tikai kā pēdējo līdzekli

Kubernetes ir divas iespējas iebÅ«vētajiem profiliem: runtime/default Šø docker/default. Abus ievieÅ” konteinera izpildlaiks, nevis Kubernetes. Tāpēc tie var atŔķirties atkarÄ«bā no izmantotās izpildlaika vides un tās versijas.

Citiem vārdiem sakot, izpildlaika maiņas rezultātā konteineram var bÅ«t piekļuve citai sistēmas zvanu kopai, ko tas var izmantot vai neizmantot. Lielākā daļa izpildlaiku izmanto Docker ievieÅ”ana. Ja vēlaties izmantot Å”o profilu, lÅ«dzu, pārliecinieties, ka tas jums ir piemērots.

profils docker/default ir novecojis kopÅ” Kubernetes 1.11, tāpēc izvairieties to izmantot.

Manuprāt, profils runtime/default lieliski piemērots mērÄ·im, kuram tā tika izveidota: lietotāju aizsardzÄ«bai no riskiem, kas saistÄ«ti ar komandas izpildi docker run uz viņu automaŔīnām. Tomēr, runājot par biznesa lietojumprogrammām, kas darbojas Kubernetes klasteros, es uzdroÅ”inos iebilst, ka Ŕāds profils ir pārāk atvērts un izstrādātājiem vajadzētu koncentrēties uz profilu izveidi savām lietojumprogrammām (vai lietojumprogrammu veidiem).

Padoms # 3: izveidojiet seccomp profilus noteiktām lietojumprogrammām. Ja tas nav iespējams, izveidojiet profilus lietojumprogrammu veidiem, piemēram, izveidojiet papildu profilu, kas ietver visas Golang lietojumprogrammas tīmekļa API. Izmantojiet izpildlaiku/noklusējumu tikai kā pēdējo līdzekli.

Nākamajos rakstos es apskatÄ«Å”u, kā izveidot SecDevOps iedvesmotus seccomp profilus, automatizēt tos un pārbaudÄ«t tos konveijerā. Citiem vārdiem sakot, jums nebÅ«s attaisnojuma nejaunināt uz lietojumprogrammu profiliem.

4. Neierobežots NAV risinājums.

No pirmais Kubernetes droŔības audits izrādÄ«jās, ka pēc noklusējuma seccomp atspējota. Tas nozÄ«mē, ka, ja neesat iestatÄ«jis PodSecurityPolicy, kas to iespējos klasterÄ«, darbosies visi podi, kuriem seccomp profils nav definēts seccomp=unconfined.

DarboÅ”anās Å”ajā režīmā nozÄ«mē, ka tiek zaudēts viss izolācijas slānis, kas aizsargā kopu. Å o pieeju droŔības speciālisti neiesaka.

Padoms # 4: nevienam klastera konteineram nevajadzētu darboties seccomp=unconfined, Ä«paÅ”i ražoÅ”anas vidēs.

5. "Audita režīms"

Å is punkts nav unikāls Kubernetes, taču joprojām ietilpst kategorijā ā€œlietas, kas jāzina pirms darba sākÅ”anasā€.

Kā tas notiek, seccomp profilu izveide vienmēr ir bijusi sarežģīta un lielā mērā ir atkarÄ«ga no izmēģinājumiem un kļūdām. Fakts ir tāds, ka lietotājiem vienkārÅ”i nav iespējas tos pārbaudÄ«t ražoÅ”anas vidēs, neriskējot ā€œnomestā€ lietojumprogrammu.

Pēc Linux kodola 4.14 izlaiÅ”anas kļuva iespējams palaist profila daļas audita režīmā, ierakstot informāciju par visiem sistēmas izsaukumiem syslog, bet nebloķējot tos. Å o režīmu var aktivizēt, izmantojot parametru SCMT_ACT_LOG:

SCMP_ACT_LOG: seccomp neietekmēs pavedienu, kas veic sistēmas izsaukumu, ja tas neatbilst nevienam filtra noteikumam, taču informācija par sistēmas zvanu tiks reģistrēta.

Å eit ir tipiska Ŕīs funkcijas izmantoÅ”anas stratēģija:

  1. Atļaut sistēmas zvanus, kas nepiecieÅ”ami.
  2. Bloķējiet zvanus no sistēmas, par kuriem jūs zināt, ka tie nebūs noderīgi.
  3. Reģistrēt informāciju par visiem citiem zvaniem žurnālā.

VienkārÅ”ots piemērs izskatās Ŕādi:

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

Taču atcerieties, ka jums ir jābloķē visi zvani, par kuriem jÅ«s zināt, ka tie netiks izmantoti un kas varētu kaitēt klasterim. Labs pamats saraksta sastādÄ«Å”anai ir oficiālais Docker dokumentācija. Tajā ir detalizēti paskaidrots, kuri sistēmas zvani noklusējuma profilā ir bloķēti un kāpēc.

Tomēr ir viens āķis. Lai gan SCMT_ACT_LOG KopÅ” 2017. gada beigām to atbalsta Linux kodols, tas Kubernetes ekosistēmā ienāca tikai salÄ«dzinoÅ”i nesen. Tāpēc, lai izmantotu Å”o metodi, jums bÅ«s nepiecieÅ”ams Linux kodols 4.14 un runC versija, kas nav zemāka v1.0.0-rc9.

Padoms # 5: Audita režīma profilu testÄ“Å”anai ražoÅ”anā var izveidot, apvienojot melnos un baltos sarakstus, un visus izņēmumus var reÄ£istrēt.

6. Izmantojiet baltos sarakstus

Baltā saraksta izveide prasa papildu pÅ«les, jo jums ir jāidentificē katrs lietojumprogrammai nepiecieÅ”amais zvans, taču Ŕī pieeja ievērojami uzlabo droŔību:

Ir ļoti ieteicams izmantot baltā saraksta pieeju, jo tā ir vienkārŔāka un uzticamāka. Melnais saraksts bÅ«s jāatjaunina ikreiz, kad tiek pievienots potenciāli bÄ«stams sistēmas izsaukums (vai bÄ«stams karodziņŔ/opcija, ja tas ir melnajā sarakstā). Turklāt bieži vien ir iespējams mainÄ«t parametra attēlojumu, nemainot tā bÅ«tÄ«bu un tādējādi apiet melnā saraksta ierobežojumus.

Go lietojumprogrammām es izstrādāju Ä«paÅ”u rÄ«ku, kas tiek pievienots lietojumprogrammai un apkopo visus izpildes laikā veiktos zvanus. Piemēram, Ŕādai lietojumprogrammai:

package main

import "fmt"

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

... sāksim gosystract tā:

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

... un mēs iegÅ«stam Ŕādu rezultātu:

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

Pagaidām Å”is ir tikai piemērs ā€” sÄ«kāka informācija par rÄ«kiem sekos.

Padoms # 6: Atļaujiet tikai tos zvanus, kas jums patieŔām ir nepiecieÅ”ami, un bloķējiet visus pārējos.

7. Ielieciet pareizos pamatus (vai sagatavojieties negaidītai uzvedībai)

Kodols ieviesÄ«s profilu neatkarÄ«gi no tā, ko jÅ«s tajā ierakstāt. Pat ja tas nav tieÅ”i tas, ko jÅ«s gribējāt. Piemēram, ja bloķējat piekļuvi tādiem zvaniem kā exit vai exit_group, konteiners nevarēs pareizi izslēgties un pat vienkārÅ”a komanda, piemēram, echo hi pakārt viņuo uz nenoteiktu laiku. Rezultātā jÅ«s saņemsit lielu CPU lietojumu klasterÄ«:

Seccomp in Kubernetes: 7 lietas, kas jums jāzina no paŔa sākuma

Šādos gadījumos palīgā var nākt utilīta strace - tas parādīs, kāda varētu būt problēma:

Seccomp in Kubernetes: 7 lietas, kas jums jāzina no paŔa sākuma
sudo strace -c -p 9331

Pārliecinieties, vai profilos ir visi sistēmas izsaukumi, kas lietojumprogrammai ir nepiecieÅ”ami izpildlaikā.

Padoms # 7: pievērsiet uzmanÄ«bu detaļām un pārliecinieties, vai visi nepiecieÅ”amie sistēmas zvani ir iekļauti baltajā sarakstā.

Ar Å”o tiek noslēgta pirmā daļa rakstu sērijai par seccomp izmantoÅ”anu programmā Kubernetes SecDevOps garā. Nākamajās daļās mēs runāsim par to, kāpēc tas ir svarÄ«gi un kā automatizēt procesu.

PS no tulka

Lasi arī mūsu emuārā:

Avots: www.habr.com

Pievieno komentāru