Megjegyzés fordítás.: Bemutatjuk a brit ASOS.com cég idősebb alkalmazásbiztonsági mérnökének írásának fordítását. Ezzel kezdi el a publikációk sorozatát, amely a Kubernetes biztonságának javításáról szól a seccomp használatával. Ha a bevezetés tetszik az olvasóknak, követni fogjuk a szerzőt, és folytatjuk a témához kapcsolódó jövőbeli anyagaival.

Ez a cikk az első egy sorozatból, amely arról szól, hogyan lehet seccomp profilokat létrehozni a SecDevOps szellemében, varázslat és bűbáj nélkül. Az első részben az alapokról és a seccomp Kubernetes-ben történő megvalósításának belső részleteiről fogok beszélni.
A Kubernetes ökoszisztéma elegendő változatosságot kínál a konténerek biztonságának és elszigetelésének biztosítására. A cikk a Secure Computing Mode-al foglalkozik, amelyet szintén ismernek seccomp. A lényeg a konténerek által végrehajtható rendszerhívások szűrése.
Miért fontos ez? A konténer csak egy folyamat, amelyet egy adott gépen futtatnak. Ez az alkalmazásokkal együtt használja a magot. Ha a konténerek bármilyen rendszerhívást végrehajthatnának, hamarosan a kártékony programok kihasználhatnák ezt, hogy megkerüljék a konténerek elszigeteltségét, és hatással legyenek más alkalmazásokra: információkat szerezhetnének meg, megváltoztathatnák a rendszerbeállításokat, stb.
A seccomp profilok meghatározzák, hogy mely rendszerhívásoknak kell engedélyezettnek vagy tiltottaknak lennie. A konténer futási környezete aktiválja őket a futtatás során, hogy a mag ellenőrizhesse a végrehajtásukat. Az ilyen profilok alkalmazása lehetővé teszi a támadási felület korlátozását és a kár minimalizálását, ha bármely program a konténeren belül (tehát a függőségeid, vagy azok függőségei) olyan dolgokat kezd el végezni, amiket nem engedélyeztek neki.
Az alapok megértése
A seccomp alapprofil három elemet tartalmaz: defaultAction, architectures SysWOW64 archMap, ennek eredményeként a lekérdezések olyan formát öltenek, mint a fent említett. 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"
}
]
}()
defaultAction meghatározza a szabványos rendszerek hívási sorsát, amelyet nem határoztak meg a szakaszban syscalls. Az egyszerűsítés érdekében összpontosítsunk a két fő jelentésre, amelyet használni fogunk:
-
SCMP_ACT_ERRNO— leállítja a rendszerhívás végrehajtását, -
SCMP_ACT_ALLOW— engedélyezi.
A részben architectures a célarchitektúrák vannak felsorolva. Ez fontos, mert a kernel szintjén alkalmazott szűrő a rendszerhívások azonosítóitól függ, nem pedig a neveiktől, amelyek a profilban vannak megadva. A konténer futtatási környezete ezeket az azonosítókat összehasonlítja. A lényeg az, hogy a rendszerhívások teljesen eltérő azonosítókkal rendelkezhetnek attól függően, hogy a rendszer architektúrája milyen. Például a rendszerhívás recvfrom (amelyet információk szerzésére használnak a socket-től) ID = 64 a x64 rendszereken és ID = 517 a x86 rendszereken. megtalálhatja az összes rendszerhívás listáját az x86-x64 architektúrákhoz.
A szakaszban syscalls minden rendszerhívás szerepel, és meg van határozva, hogy mit kell velük tenni. Például létrehozhatunk egy fehér listát, ha beállítjuk defaultAction Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata SCMP_ACT_ERRNO, és a hívásoknak a szakaszban syscalls hozzárendelhetjük SCMP_ACT_ALLOW. Ezzel csak azok a hívások engedélyezettek, amelyek a szakaszban vannak megadva, és minden más tilos. A fekete lista esetén cserélje meg az értékeket syscalls, és az akciókat fordítva. defaultAction Most néhány szót kell mondani a kevésbé nyilvánvaló részletekről. Vegye figyelembe, hogy az alábbi ajánlások abból adódnak, hogy Ön üzleti alkalmazások sorozatát fejleszti a Kubernetesben, és fontos az alacsonyabb jogosultságokkal való működés.
1. AllowPrivilegeEscalation=false
securityContext
A a konténernek van egy paramétere AllowPrivilegeEscalation . Ha ezértékre van állítva, a konténerek a beállított ( hamis) bitnek megfelelően indulnakonno_new_priv Ennek a paraméternek a mellékhatása, ha be van állítva
(alapértelmezett érték), hogy a konténer futtatási környezete a seccomp profilt a folyamat indítása során alkalmazza. Így minden rendszerhívás, amely a futtatási környezet belső folyamatait igényli (például felhasználói/csoportazonosítók beállítása, bizonyos képességek eltávolítása), engedélyezve kell hogy legyen a profilban. igaz A konténernek, amely egy egyszerű
echo hi , a következő engedélyekre lesz szüksége:, a következő engedélyekre lesz szükség:
{
"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"
}
]
}()
… ezek helyett:
{
"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"
}
]
}()
De mégis, miért jelent ez problémát? Személy szerint kerülném a következő rendszerhívások fehérlistára helyezését (ha nincs rá valódi szükség): capset, set_tid_address, setgid, setgroups és setuid. A valódi nehézség abban áll, hogy amikor engedélyezed azokat a folyamatokat, amelyeket teljes mértékben nem tudsz ellenőrizni, a profilokat a konténer futtatási környezetének megvalósításához kötöd. Más szóval, előfordulhat, hogy miután frissítetted a konténer futtatási környezetét (akár te, akár valószínűbb, hogy a felhőszolgáltató), a konténerek hirtelen megállnak.
1. Tanács: Futtass konténereket a következő beállítással: AllowPrivilegeEscalation=false. Ez csökkenti a seccomp profilok méretét, és érzékenyebbé teszi őket a konténer futtatási környezetének változásaival szemben.
2. Seccomp profilok beállítása konténer szinten
A seccomp profil beállítható pod szinten:
annotations:
seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"… vagy konténer szinten:
annotations:
container.security.alpha.kubernetes.io/: "localhost/profile.json"Kérlek, vedd figyelembe, hogy a fenti szintaxis megváltozik, amikor a Kubernetes seccomp (ez az esemény már a következő Kubernetes kiadásban — 1.18 — várható).
Kevesen tudják, hogy a Kubernetes-ben mindig is volt egy , ami miatt a seccomp profilokat alkalmazták . A végrehajtási környezet részben kompenzálja ezt a hiányosságot, azonban ez a konténer továbbra is a pod-okban marad, mivel az infrastruktúrájuk beállításához használják.
A probléma az, hogy ez a konténer mindig a következővel indul: AllowPrivilegeEscalation=true, ami az 1. pontban említett problémákhoz vezet, és ezt megváltoztatni nem lehet.
Seccomp profilok alkalmazásával konténer szinten elkerülheted ezt a csapdát, és olyan profilt hozhatsz létre, amely a konkrét konténerhez van 'hangolva'. Ezt addig kell tenni, amíg a fejlesztők meg nem javítják a hibát, és egy új verzió (lehet, hogy 1.18?) elérhetővé nem válik mindenki számára.
2. tipp: Állíts be seccomp profilokat konténer szinten.
Gyakorlati értelemben ez a szabály általában egy általános válasz a következő kérdésre: 'Miért működik a seccomp profilom a docker run, de miért nem működik a Kubernetes klaszterben történő telepítés után?'.
3. Használj runtime/defaultot csak végső esetben
A Kubernetes-ben két beépített profil lehetőség létezik: runtime/default és docker/default. Mindkettőt a konténer végrehajtási környezete valósítja meg, nem a Kubernetes. Ezért eltérhetnek attól függően, hogy milyen végrehajtási környezetet használnak és annak verzióját.
Más szavakkal, ha a konténer végrehajtási környezetet vált, hozzáférhet egy másik rendszerhívás-csoporthoz, amelyet használhat vagy nem használhat. A legtöbb végrehajtási környezet Ha ezt a profilt szeretnéd használni, győződj meg róla, hogy megfelel neked.
A profil docker/default Kubernetes 1.11 óta elavultnak számít, ezért kerüld a használatát.
A véleményem szerint a profil runtime/default kiválóan alkalmas a célokra, amelyekért létrehozták: védeni a felhasználókat a parancs futtatásával járó kockázatoktól docker run a gépeiken. Azonban ha üzleti alkalmazásokról van szó, amelyek Kubernetes klaszterekben futnak, bátran állíthatom, hogy ez a profil túl nyitott, és a fejlesztőknek a saját alkalmazásaikra (vagy alkalmazástípusokra) szabott profilok létrehozására kellene összpontosítaniuk.
3. tipp: Hozz létre seccomp profilokat konkrét alkalmazásokhoz. Ha ez nem lehetséges, foglalkozz az alkalmazástípusokhoz tartozó profilokkal, például hozz létre egy kiterjesztett profilt, amely tartalmazza az összes web-API-t, ami a Golang alkalmazásban található. Csak végső esetben használd a runtime/default-ot.
A jövőbeli publikációkban arról mesélek, hogyan lehet seccomp profilokat létrehozni SecDevOps szellemben, automatizálni és tesztelni őket a pipeline-okban. Más szavakkal, nem marad mentség, miért ne lehetne váltani az adott alkalmazásokhoz készült profilokra.
4. Az Unconfined NEM lehetőség
A kiderült, hogy alapértelmezés szerint . Ez azt jelenti, hogy ha nem állítja be a PodSecurityPolicy-t, amely bekapcsolja azt a klaszterben, minden pod, amelyhez nem lett seccomp profil meghatározva, az seccomp=unconfined.
módban fog futni. Ilyen módban működni azt jelenti, hogy elveszik egy egész izolációs réteg, amely védi a klasztert. Az ilyen megközelítést a biztonsági szakemberek nem ajánlják.
4. tanács: Egyetlen konténer sem működhet a klaszterben seccomp=unconfined, különösen production környezetekben.
5. „Audit mód”
Ez a pont nem egyedi a Kubernetes számára, de mégis beleesik abba a kategóriába, hogy „amit jó tudni már a kezdetekkor”.
Hagyományosan a seccomp profilok létrehozása mindig is nehéz feladat volt, és jelentős mértékben próbálkozások és hibák módszerén alapult. Az a helyzet, hogy a felhasználóknak egyszerűen nincs lehetőségük ellenőrizni őket production környezetben anélkül, hogy „megbuktatnák” az alkalmazást.
A Linux 4.14-es kernel megjelenésével lehetőség nyílt arra, hogy a profil részeit audit módban fussanak, rögzítve a syslog-ba az összes rendszerhívás információját, de nem blokkolva azokat. Ezt a módot a SCMT_ACT_LOG:
SCMP_ACT_LOG: a seccomp nem befolyásolja a hívást intéző szál működését, ha az nem esik egyetlen szűrőszabály alá sem, viszont a rendszerhívás információja bejegyzésre kerül a naplóba.
Íme egy tipikus stratégia ennek a lehetőségnek a használatához:
- Engedélyezze azokat a rendszerhívásokat, amelyek szükségesek.
- Blokkolja azokat a rendszerhívásokat, amelyekről tudja, hogy nem lesznek hasznosak.
- Minden további hívás információját naplózza.
Egy egyszerű példa a következőképpen néz ki:
{
"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"
}
]
}()
De ne felejtsd el, hogy blokkolnod kell minden hívást, amiről tudható, hogy nem fog használatban lenni, és amelyek potenciálisan kárt okozhatnak a klaszterben. Jó alapot nyújt az hivatalos . Részletesen magyarázza el, hogy mely rendszerszintek vannak letiltva az alapértelmezett profilban és miért.
De van egy csapda. Bár SCMT_ACT_LOG a Linux kernel támogatja 2017 óta, a Kubernetes ökoszisztémában csak viszonylag nemrégiben lépett be. Ezért ennek a módszernek a használatához 4.14-es Linux kernel és nem alacsonyabb runC verzió szükséges .
5. tipp: A teszteléshez készített audit módú profil létrehozható a fekete és fehér listák kombinálásával, míg minden kivételt naplózni kell.
6. Használj fehér listákat
A fehér listák kialakítása további erőfeszítéseket igényel, mivel minden hívást azonosítani kell, amelyre szüksége lehet az alkalmazásnak, azonban ez a megközelítés jelentősen növeli a biztonságot:
Határozottan ajánlott a fehér listák alapján történő megközelítést használni, mivel ez egyszerűbb és megbízhatóbb. A fekete listát minden alkalommal frissíteni kell, amikor egy potenciálisan veszélyes rendszerszint hívást (vagy veszélyes zászlót/paramétert, ha a fekete listán vannak) adnak hozzá. Ezen kívül gyakran meg lehet változtatni a paraméter megjelenését anélkül, hogy annak lényegét megváltoztatnánk, ezzel megkerülve a fekete lista korlátozásait.
Go programokhoz kifejlesztettem egy speciális eszközt, amely kíséri az alkalmazást, és összegyűjti az összes hívást, amelyet futás közben végeztek. Például az alábbi alkalmazás esetében:
package main
import "fmt"
func main() {
fmt.Println("teszt")
} … futtatjuk a gosystract-ot így nézett ki:
go install https://github.com/pjbgf/gosystract
gosystract --template='{{- range . }}{{printf "%s", .Name}}{{- end}}' application-path… és a következő eredményt kapjuk:
"sched_yield",
"futex",
"write",
"mmap",
"exit_group",
"madvise",
"rt_sigprocmask",
"getpid",
"gettid",
"tgkill",
"rt_sigaction",
"read",
"getpgrp",
"arch_prctl",Ez csak egy példa — a részletek az eszközkészletről később következnek.
6. Tanács: Csak azokat a hívásokat engedélyezze, amelyek valóban szükségesek, és blokkolja az összes többit.
7. Helyezze el a helyes alapokat (vagy készüljön fel a váratlan viselkedésre)
A kernel figyelemmel kíséri a profil betartását, függetlenül attól, hogy mit írt bele. Még ha nem is egészen olyan, amilyet szeretett volna. Például, ha blokkolja a hívások hozzáférését, mint például exit vagy exit_group, a konténer nem tudja megfelelően kilépni, és még egy egyszerű parancs is, mint például , a következő engedélyekre lesz szüksége: határozatlan ideig. Ennek következtében magas CPU terhelést kap a klaszterben:

Ilyen esetekben hasznos lehet az strace — megmutatja, hol lehet a probléma:

sudo strace -c -p 9331
Győződjön meg arról, hogy a profilok tartalmazzák az összes rendszerhívást, amelyek az alkalmazás működése alatt szükségesek.
7. Tanács: Figyelmesnek kell lennie a részletekre, és ellenőrizze, hogy minden szükséges rendszerhívás belekerült a fehérlistába.
Ez a cikksorozat első része a seccomp használatáról a Kubernetesben a SecDevOps szellemében a végéhez közelít. A következő részekben arról fogunk beszélni, hogy miért fontos, és hogyan lehet automatizálni a folyamatot.
Fejlesztési eszközök, amelyek Kubernetesben futnak
Olvasson további információkat a blogunkban:
- «»;
- «»;
- «»;
- «».
Forrás: habr.com
