Seccomp yn Kubernetes: 7 dingen dy't jo moatte witte fan it begjin ôf

Noat. transl.: Wy presintearje oan jo oandacht de oersetting fan in artikel troch in senior applikaasje befeiligingsingenieur by it Britske bedriuw ASOS.com. Dêrmei begjint hy in searje publikaasjes wijd oan it ferbetterjen fan feiligens yn Kubernetes troch it brûken fan seccomp. As lêzers de ynlieding leuk fine, sille wy de auteur folgje en trochgean mei syn takomstige materialen oer dit ûnderwerp.

Seccomp yn Kubernetes: 7 dingen dy't jo moatte witte fan it begjin ôf

Dit artikel is it earste yn in searje berjochten oer hoe't jo seccomp-profilen kinne oanmeitsje yn 'e geast fan SecDevOps, sûnder gebrûk te meitsjen fan magy en hekserij. Yn diel 1 sil ik de basis en ynterne details dekke fan it ymplementearjen fan seccomp yn Kubernetes.

It Kubernetes-ekosysteem biedt in breed ferskaat oan manieren om konteners te befeiligjen en te isolearjen. It artikel giet oer Secure Computing Mode, ek wol bekend as secomp. De essinsje dêrfan is om de systeemoproppen te filterjen dy't beskikber binne foar útfiering troch konteners.

Wêrom is it wichtich? In kontener is gewoan in proses dat rint op in spesifike masine. En it brûkt de kernel krekt lykas oare applikaasjes. As konteners alle systeemoproppen koene útfiere, soe malware heul gau profitearje fan dit om kontenerisolaasje te omgean en oare applikaasjes te beynfloedzjen: ynformaasje ûnderskeppe, systeemynstellingen feroarje, ensfh.

seccomp-profilen definiearje hokker systeemoproppen tastien of útskeakele wurde moatte. De kontener-runtime aktivearret se as it begjint, sadat de kernel har útfiering kontrolearje kin. It brûken fan sokke profilen lit jo de oanfalsvektor beheine en skea ferminderje as in programma yn 'e kontener (dat is jo ôfhinklikens, of har ôfhinklikens) begjint wat te dwaan dat it net tastien is.

Getting nei de basis

It basis secomp-profyl omfettet trije eleminten: defaultAction, architectures (of archMap) en 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-secomp.json)

defaultAction bepaalt it standertlot fan elke systeemoprop dy't net spesifisearre is yn 'e seksje syscalls. Om dingen makliker te meitsjen, litte wy ús rjochtsje op 'e twa haadwearden dy't sille wurde brûkt:

  • SCMP_ACT_ERRNO - blokkearret de útfiering fan in systeemoprop,
  • SCMP_ACT_ALLOW - stiet ta.

section architectures doel arsjitektuer wurde neamd. Dit is wichtich om't it filter sels, tapast op it kearnnivo, hinget fan systeemoprop-identifiers, en net fan har nammen dy't yn it profyl oantsjutte binne. De kontener-runtime sil se oerienkomme mei identifiers foar gebrûk. It punt is dat systeemoproppen folslein ferskillende ID's kinne hawwe ôfhinklik fan 'e systeemarsjitektuer. Bygelyks, systeem oprop recvfrom (brûkt om ynformaasje te ûntfangen fan 'e socket) hat ID = 64 op x64-systemen en ID = 517 op x86. it is kinne jo fine in list fan alle systeem oproppen foar x86-x64 arsjitektuer.

Yn de seksje syscalls listet alle systeemoproppen en spesifisearret wat mei har te dwaan. Jo kinne bygelyks in whitelist meitsje troch yn te stellen defaultAction op SCMP_ACT_ERRNO, en ropt yn 'e seksje syscalls tawize SCMP_ACT_ALLOW. Sa tastean jo allinnich oproppen spesifisearre yn de seksje syscalls, en ferbiede alle oaren. Foar de swarte list moatte jo de wearden feroarje defaultAction en aksjes nei it tsjinoerstelde.

No moatte wy in pear wurden sizze oer nuânses dy't net sa dúdlik binne. Tink derom dat de oanbefellings hjirûnder oannimme dat jo in line fan saaklike applikaasjes ynsette op Kubernetes en jo wolle dat se rinne mei it minste oantal privileezjes mooglik.

1. AllowPrivilegeEscalation=falsk

В securityContext container hat in parameter AllowPrivilegeEscalation. As it is ynstallearre yn false, konteners sille begjinne mei (on) bytsje no_new_priv. De betsjutting fan dizze parameter is dúdlik út 'e namme: it foarkomt dat de kontener nije prosessen mei mear privileezjes lanseart as it sels hat.

In side-effekt fan dizze opsje wurdt ynsteld op true (standert) is dat de kontener-runtime it seccomp-profyl tapast oan it begjin fan it opstartproses. Sa moatte alle systeemoproppen dy't nedich binne om ynterne runtime-prosessen út te fieren (bgl. brûker-/groep-ID's ynstelle, bepaalde mooglikheden falle) yn it profyl ynskeakele wurde.

Nei in kontener dy't triviale dingen docht echo hi, sille de folgjende tagongsrjochten nedich wêze:

{
    "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-secomp.json)

... ynstee fan dizze:

{
    "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-secomp.json)

Mar wer, wêrom is dit in probleem? Persoanlik soe ik mije it whitelistjen fan de folgjende systeemoproppen (útsein as d'r echt ferlet is foar har): capset, set_tid_address, setgid, setgroups и setuid. De wirklike útdaging is lykwols dat troch prosessen te tastean wêr't jo absolút gjin kontrôle oer hawwe, jo profilen bine oan 'e ymplemintaasje fan kontenerruntime. Mei oare wurden, op in dei kinne jo fine dat nei it bywurkjen fan 'e kontener-runtime-omjouwing (sawol troch jo as, wierskynliker, troch de cloud-tsjinstferliener), de konteners ynienen stopje mei rinnen.

Ried nûmer 1: Run konteners mei AllowPrivilegeEscaltion=false. Dit sil de grutte fan seccomp-profilen ferminderje en se minder gefoelich meitsje foar feroaringen yn 'e kontener-runtime-omjouwing.

2. Setting seccomp profilen op de container nivo

It seccomp-profyl kin wurde ynsteld op it podnivo:

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

... of op kontenernivo:

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

Tink derom dat de boppesteande syntaksis sil feroarje as Kubernetes seccomp sil GA wurde (dit barren wurdt ferwachte yn 'e folgjende útjefte fan Kubernetes - 1.18 - likernôch transl.).

Net folle minsken witte dat Kubernetes altyd hie bugdy't feroarsake seccomp-profilen wurde tapast op pauze container. De runtime-omjouwing kompensearret foar in part foar dizze tekoart, mar dizze kontener ferdwynt net fan 'e pods, om't it wurdt brûkt om har ynfrastruktuer te konfigurearjen.

It probleem is dat dizze kontener altyd begjint mei AllowPrivilegeEscalation=true, liedt ta de problemen útsprutsen yn paragraaf 1, en dit kin net feroare wurde.

Troch seccomp-profilen op it kontenernivo te brûken, foarkomme jo dizze falkûle en kinne jo in profyl meitsje dat is ôfstimd op in spesifike kontener. Dit sil dien wurde moatte oant de ûntwikkelders de brek reparearje en de nije ferzje (miskien 1.18?) foar elkenien beskikber wurdt.

Ried nûmer 2: Set secomp-profilen op it kontenernivo.

Yn praktyske sin tsjinnet dizze regel meastentiids as in universele antwurd op de fraach: "Wêrom wurket myn seccomp-profyl mei docker runmar wurket net nei it ynsetten nei in Kubernetes-kluster?

3. Brûk runtime / standert allinnich as lêste ynstânsje

Kubernetes hat twa opsjes foar ynboude profilen: runtime/default и docker/default. Beide wurde ymplementearre troch de container runtime, net Kubernetes. Dêrom kinne se ferskille ôfhinklik fan 'e brûkte runtime-omjouwing en har ferzje.

Mei oare wurden, as gefolch fan it feroarjen fan runtime, kin de kontener tagong hawwe ta in oare set fan systeemoproppen, dy't it al of net brûke kin. De measte runtimes brûke Docker ymplemintaasje. As jo ​​​​dit profyl brûke wolle, soargje dan asjebleaft dat it geskikt is foar jo.

Profyl docker/default is ôfret sûnt Kubernetes 1.11, dus foarkom it te brûken.

Yn myn miening, profyl runtime/default perfekt geskikt foar it doel wêrfoar it is makke: brûkers beskermje tsjin 'e risiko's ferbûn mei it útfieren fan in kommando docker run op harren auto's. As it lykwols giet om bedriuwsapplikaasjes dy't rinne op Kubernetes-klusters, soe ik it weagje om te beweare dat sa'n profyl te iepen is en ûntwikkelders moatte har rjochtsje op it meitsjen fan profilen foar har applikaasjes (of soarten applikaasjes).

Ried nûmer 3: Meitsje secomp-profilen foar spesifike applikaasjes. As dit net mooglik is, meitsje profilen foar applikaasjetypen, meitsje bygelyks in avansearre profyl dat alle web-API's fan 'e Golang-applikaasje omfettet. Brûk runtime / standert allinich as lêste ynstânsje.

Yn takomstige berjochten sil ik dekke hoe't jo SecDevOps-ynspireare seccomp-profilen kinne oanmeitsje, automatisearje se en testen yn pipelines. Mei oare wurden, jo sille gjin ekskús hawwe om net te upgrade nei applikaasje-spesifike profilen.

4. Unbeheind is NET in opsje.

Из earste Kubernetes feiligens audit it die bliken dat standert seccomp útskeakele. Dit betsjut dat as jo net ynstelle PodSecurityPolicy, wat it yn it kluster ynskeakelje sil, sille alle pods wêrfoar it seccomp-profyl net definiearre is wurkje yn seccomp=unconfined.

Operearje yn dizze modus betsjut dat in hiele laach fan isolaasje wurdt ferlern dat beskermet it kluster. Dizze oanpak wurdt net oanrikkemandearre troch feiligenseksperts.

Ried nûmer 4: Gjin kontener yn it kluster moat yn rinne seccomp=unconfined, benammen yn produksjeomjouwings.

5. "Kontrôlemodus"

Dit punt is net unyk foar Kubernetes, mar falt dochs yn 'e kategory "dingen om te witten foardat jo begjinne".

As it bart, hat it meitsjen fan seccomp-profilen altyd útdaagjend west en fertrout swier op probearjen en flater. It feit is dat brûkers gewoan net de kâns hawwe om se te testen yn produksjeomjouwings sûnder it risiko dat de applikaasje "falle".

Nei de frijlitting fan 'e Linux-kernel 4.14 waard it mooglik dielen fan in profyl yn kontrôlemodus út te fieren, ynformaasje oer alle systeemoproppen yn syslog op te nimmen, mar sûnder se te blokkearjen. Jo kinne dizze modus aktivearje mei de parameter SCMT_ACT_LOG:

SCMP_ACT_LOG: secomp sil gjin ynfloed hawwe op de thread dy't de systeemoprop makket as it net oerienkomt mei in regel yn it filter, mar ynformaasje oer de systeemoprop sil ynlogd wurde.

Hjir is in typyske strategy foar it brûken fan dizze funksje:

  1. Tastean systeemoproppen dy't nedich binne.
  2. Blokkearje oproppen fan it systeem dat jo witte dat it net nuttich sil wêze.
  3. Record ynformaasje oer alle oare oproppen yn it log.

In ferienfâldige foarbyld sjocht der sa út:

{
    "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-mingd-secomp.json)

Mar tink derom dat jo alle oproppen moatte blokkearje dy't jo witte dat se net sille wurde brûkt en dat it kluster mooglik skea kin. In goede basis foar it gearstallen fan in list is de amtner Docker dokumintaasje. It ferklearret yn detail hokker systeemoproppen binne blokkearre yn it standertprofyl en wêrom.

D'r is lykwols ien fangen. Alhoewol SCMT_ACT_LOG stipe troch de Linux-kernel sûnt it ein fan 2017, kaam it pas relatyf koartlyn yn it Kubernetes-ekosysteem. Dêrom, om dizze metoade te brûken, sille jo in Linux-kernel 4.14 en runC-ferzje net leger hawwe v1.0.0-rc9.

Ried nûmer 5: In audit modus profyl foar testen yn produksje kin makke wurde troch in kombinaasje fan swarte en wite listen, en alle útsûnderings kinne wurde oanmeld.

6. Brûk whitelists

Whitelisting fereasket ekstra ynspanning, om't jo elke oprop moatte identifisearje dy't de applikaasje miskien nedich is, mar dizze oanpak ferbetteret de feiligens sterk:

It is tige oan te rieden om de whitelist-oanpak te brûken, om't it ienfâldiger en betrouber is. De swarte list sil bywurke wurde moatte as in mooglik gefaarlike systeemoprop (of in gefaarlike flagge/opsje as it op 'e swarte list stiet) tafoege wurdt. Dêrnjonken is it faaks mooglik om de fertsjintwurdiging fan in parameter te feroarjen sûnder syn essinsje te feroarjen en dêrmei de beheiningen fan 'e swarte list om te gean.

Foar Go-applikaasjes haw ik in spesjaal ark ûntwikkele dat de applikaasje begeliedt en alle oproppen sammelt dy't makke binne tidens de útfiering. Bygelyks, foar de folgjende applikaasje:

package main

import "fmt"

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

... litte wy begjinne gosystract like this:

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

... en wy krije it folgjende resultaat:

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

Foar no is dit gewoan in foarbyld - mear details oer de ark sille folgje.

Ried nûmer 6: Tastean allinich dy petearen dy't jo echt nedich binne en blokkearje alle oaren.

7. De juste fûneminten lizze (of tariede op ûnferwacht gedrach)

De kernel sil it profyl ôftwinge, nettsjinsteande wat jo deryn skriuwe. Sels as it net krekt is wat jo woene. Bygelyks, as jo blokkearje tagong ta petearen lykas exit of exit_group, sil de kontener net goed kinne ôfslute en sels in ienfâldich kommando lykas echo hi hingje him opo foar in ûnbepaalde perioade. As gefolch krije jo heech CPU-gebrûk yn it kluster:

Seccomp yn Kubernetes: 7 dingen dy't jo moatte witte fan it begjin ôf

Yn soksoarte gefallen kin in hulpprogramma ta de rêding komme strace - it sil sjen litte wat it probleem kin wêze:

Seccomp yn Kubernetes: 7 dingen dy't jo moatte witte fan it begjin ôf
sudo strace -c -p 9331

Soargje derfoar dat de profilen alle systeemoproppen befetsje dy't de applikaasje nedich is by runtime.

Ried nûmer 7: Jou omtinken oan detail en soargje derfoar dat alle nedige systeemoproppen op wite list steane.

Dit konkludearret it earste diel fan in searje artikels oer it brûken fan seccomp yn Kubernetes yn 'e geast fan SecDevOps. Yn 'e folgjende dielen sille wy prate oer wêrom dit wichtich is en hoe it proses te automatisearjen.

PS fan oersetter

Lês ek op ús blog:

Boarne: www.habr.com

Add a comment