Biztonsági kérdések

A konténerek biztonsága kiemelt fontosságú az alkalmazások védelme és az adatok biztonságának megőrzése érdekében. Az utolsó a fejezetben áttekintjük a konténerek néhány biztonsági kérdését, beleértve a konténerizáció biztonsági szempontú előnyeit és kihívásait, valamint bemutatunk néhány, a gyakorlatban is jól hasznosítható módszert.

Szükséges eszközök:

Windows, MacOS vagy Linux operációs rendszerű számítógép, telepített Docker szoftverrel.

Feldolgozási idő:

Kb. 1 óra, a gyakorlati feladatok megoldására további 1 óra.

A konténerek működtetése során több, informatikai biztonsági szempont is felmerül, lássunk néhányat ezek közül! A legnagyobb kockázatot a felhasználók ellenőrizetlen konténerei jelentik, elsősorban akkor, ha nincsenek megfelelő intézkedések a felhasználók tevékenységének ellenőrzésére és korlátozására. A leggyakoribb kockázatok az alábbiak:

  1. Biztonsági sérülékenységek: egy konténer használatba vétele előtt azt ellenőrizni kell és ki kell értékelni az elindításának kockázatait. Kifejezetten kockázatos, ha a felhasználók ellenőrzés nélkül indíthatnak saját konténereket.

  2. Túlzott erőforráshasználat: a felhasználók által indított konténerek alapesetben korlátlan hozzáféréssel rendelkeznek a rendszer erőforrásai felett, így a teljes infrastruktúrát túlterhelhetik. Ennek következtében nem csak a szóban forgó alkalmazás, hanem a gépen futó más szolgáltatások is teljesítmény csökkentést szenvedhetnek el, vagy teljes egészében elérhetetlenné válhatnak.

  3. Adathozzáférés korlátozása: a konténerek indításának engedélyezése kockázatokat jelenthet az adathozzáférés tekintetében is. A felhasználók hozzáférhetnek olyan adatokhoz is, amelyeket normál helyzetben az operációs rendszer nem tenne lehetővé. Ez végső soron bizalmas információk jogosulatlan megszerzését eredményezheti.

  4. Ismeretlen forrású konténerek: amennyiben a felhasználók saját konténereket indíthatnak, az ismeretlen forrásból származók szintén biztonsági kockázatot jelenthetnek. Ezek a konténerek kártékony kódokat vagy biztonsági réseket tartalmazhatnak, amelyek végső soron a host gép rendszer stabilitását és biztonságát is veszélyeztethetik.

  5. Felügyelet és ellenőrzés: a megfelelő ellenőrzés és a felhasználók által indított konténerek felügyelete nélkül nehéz feladat a biztonsági fenyegetések, a hibás vagy rosszindulatú tevékenységet végző alkalmazások felismerése és gyors válasz adása.

  6. A union fájlrendszer működéséből fakadó adatszivárgás (a dockerhub-ra és más felületre publikált konténerek tartalmazhatnak bizalmas adatokat, amelyeket a klasszikus törléssel nem lehet törölni). Ennek okát a A union fájlrendszer fejezetben ismertettük. A MITRE ATT&CK mátrix (azon belül az ún. Containers Matrix) a támadás egyes lépései szerint csoportosítva gyűjti össze a potenciális támadási lehetőségeket és módszereket. A CIS Benchmark pedig ajánlást tesz a biztonsági szabályok fokozására – és bár ez kifejezetten docker alkalmazásokra koncentrál, de nem szabad elfeledkezni a gazda operációs rendszer megfelelő védelméről sem.

Jogosulatlan hozzáférés

A Docker működéséhez nélkülözhetetlen annak háttérfolyamata, amelynek rendszergazdai jogkörökkel kell futnia. Ez a Docker biztonsági achillesi sarka, melyet a konténereket futtató kiszolgálók felépítésekor figyelembe kell venni azért, hogy a konténerekben futó alkalmazás sem futhasson magasabb jogkörrel, mint amit neki szánunk. Az alábbiakban egy példát látunk erre: a konténer alkalmazás megjeleníti a /etc/shadow tartalmát, mely a felhasználók kódolt jelszavait tartalmazza. Ezt a fájlt normális esetben az operációs rendszer normál felhasználói nem olvashatják, de az alábbi példában ezt sikeresen meg lehet kerülni:

A védelem megkerülésére készítsünk egy egyszerű konténert, amely egyetlen parancsot hajt végre, ez a cat /etc/shadow.

FROM ubuntu:latest
LABEL maintainer="koczka.ferenc@uni-eszterhazy.hu"
CMD ["cat", "/etc/shadow"]

Építsük fel a konténert:

1koczka@columbo:~/docker$ docker build -t dockerhack .

Majd indítsuk el úgy, hogy a host gép /etc/shadow fájljával helyettesítsük a konténer /etc/shadow fájlját! A kimenetben látható, hogy a root jogosultságokkal futó konténer képes volt a fájl olvasására és meg tudta jeleníteni annak tartalmát:

1koczka@columbo:~/docker$ docker run -v /etc/shadow:/etc/shadow dockerhack
2root:$6$eSGcg3WD...ebWVEyrJ1Z2WNHCm8qnP3RWIbOAcffV7zUI/.:19627:0:99999:7:::
3daemon:*:19412:0:99999:7:::
4bin:*:19412:0:99999:7:::

Hogyan lehet az ilyen típusú támadásokat kivédeni? Azt első és legfontosabb, hogy üzemeltetőként ne tegyük lehetővé a felhasználók számára a konténerek tetszőleges paraméterekkel történő indítását, azaz felügyeljük azokat. Különösen érzékeny kérdés a kötetek csatolása, ha erre van szükség, mindig alaposan ellenőrizni kell, hogy csak a konténer csak azokat csatolhassa, amelyekre valóban engedélyt adunk. Emellett csak megbízható felhasználók számára tegyük lehetővé a konténer indítását!

Erőforrások védelme

Az erőforrások védelmére a docker számos paramétert biztosít, amelyekkel az egyes konténerek kordában tarthatók. A legfontosabb paraméterek CPU-ra és az elérhető memória nagyságának korlátozására szolgálnak. A témával kapcsolatban részletes leírás érhető el a docs.docker.com oldalon, mi most a két legfontosabb erőforrás, a processzorra és a memóriára vonatkozó korlátozását tekintjük át.

A columbo.uni-eszterhazy.hu gép 4 processzor magot tartalmaz, amit a /proc/cpuinfo „fájlból” olvastam ki. A memória nagyságát pedig a free -h --si paranccsal kérdeztem le, ez 3,9G (hát elég sovány már ez a gép, na):

koczka@columbo:~$ cat /proc/cpuinfo | grep processor
processor   : 0
processor   : 1
processor   : 2
processor   : 3

koczka@columbo:~$ free -h --si
        total   used   free   shared  buff/cache   available
Mem:     3,9G   895M   445M     1,0M        2,6G        2,7G
Swap:    7,6G    39M   7,6G

Az egyes konténerek számára elérhető erőforrások nagyságát a konténer példányok indításakor meghatározott extra paraméterekkel lehet beállítani. A processzor magok számát --cpus, a memória nagyságát a --memory szabályozza. Ahhoz, hogy a paraméterek hatását láthassuk, indítsunk el két konténert, az egyiket hagyjuk korlátozások nélkül, a másik esetében pedig az elérhető processzor magok számát állítsuk be 1-re, a memória nagyságát pedig 512Mbyte-ra! (A -d hatására tehát a konténer a háttérben fut, a -t pedig biztosítja, hogy az Linux terminál módban működjön, azaz ne lépjen ki azonnal.)

koczka@columbo:~$ docker run -t -d --name unrestricted_linux ubuntu:16.04
ebcdc01e10e3fdaf1d725f2b9b8a0e2adedfc48e4f56609c8326aa39d5dae6a1
koczka@columbo:~$ docker run -t -d --cpus="1" --memory="512M" --name restricted_linux ubuntu:16.04
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
e5961ae5f48371ef623f9fa1c95ae6f8967bc8a85344f8e7717a32205f6cfff3

Az egyes konténerek által felhasznált és elérhető memória mennyiségét a docker stats parancs jeleníti meg. Ebben leolvasható, hogy az unrestricted_linux memória limitje a rendszer teljes, 3.81GiB nagyságú területében van meghatározva, míg ennek értéke a restricted_linux esetében ez csak 512M.

CONTAINER ID   NAME                 CPU %     MEM USAGE / LIMIT    MEM %     NET I/O   BLOCK I/O   PIDS
e5961ae5f483   restricted_linux     0.00%     2.141MiB / 512MiB    0.42%     0B / 0B   0B / 0B     1
ebcdc01e10e3   unrestricted_linux   0.00%     2.324MiB / 3.81GiB   0.06%     0B / 0B   0B / 0B     1

A processzorra vonatkozó limitek itt nem láthatók, azokat a docker inspect paranccsal lehet ellenőrizni. Ennek kimenete egy JSON fájl, ami esetünkben ugyan nem túl kényelmes, de a --format paraméterrel, vagy a grep szűrővel csak a minket érdeklő, NanoCpus értéket fogjuk megjeleníteni. Az itt látható szám konkrét értéke nehezen értelmezhető, egymilliárd nanocpu felel meg egy CPU magnak. A restricted_linux esetében ez az érték éppen ennyi, az unrestricted_linux 0 értéke pedig azt jelenti, hogy arra nem vonatkozik ilyen típusú korlátozás.

koczka@columbo:~$ docker inspect restricted_linux | grep -i NanoCpus
            "NanoCpus": 1000000000,
koczka@columbo:~$ docker inspect unrestricted_linux | grep -i NanoCpus
            "NanoCpus": 0,

Végül, takarítsunk ki magunk után! Először állítsuk a konténereket, majd töröljük a hátra maradt példányokat. A felesleges fájlok eltávolításának érdekében töröljük a nem használat image-eket is.

koczka@columbo:~$ docker stop restricted_linux unrestricted_linux
restricted_linux
unrestricted_linux
koczka@columbo:~$  docker rm restricted_linux unrestricted_linux
restricted_linux
unrestricted_linux
koczka@columbo:~$ docker image prune --all -f
Deleted Images:
untagged: ubuntu:16.04
untagged: ubuntu@sha256:1f1a2d56de1d604801a9671f301190704c25d604a416f59e03c04f5c6ffee0d6
deleted: sha256:b6f50765242581c887ff1acc2511fa2d885c52d8fb3ac8c4bba131fd86567f2e
deleted: sha256:0214f4b057d78b44fd12702828152f67c0ce115f9346acc63acdf997cab7e7c8
deleted: sha256:1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61
deleted: sha256:3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea
deleted: sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069
Total reclaimed space: 134.8MB

Összefoglalás

Az utolsó fejezetünk célja, hogy bevezető képet adjon a konténerek biztonságának jelentőségéről és a megfelelő védekezési technikákról. Ebben néhány, a konténerekkel kapcsolatos biztonsági kérdés tekintettünk át, fő célunk egy ízelítő nyújtása volt az alkalmazások biztonságos működésének és adatainak védelmével kapcsolatban. Bemutatásra került a konténerizáció előnyei mellett, néhány olyan gyakorlati módszer, amely hozzájárul a biztonságos működés javításához. Példákon keresztül láttunk, hogy a konténerek ellenőrizetlen használata komoly kockázatot jelenthet, a biztonsági sérülékenységek megjelenése mellett túlzott erőforráshasználat is bekövetkezhet, ami a teljes infrastruktúra működését is negatívan befolyásolhatja. A hozzáférés-korlátozás elengedhetetlen, ellenkező esetben sérül a bizalmasság elve. Az ismeretlen forrásból származó konténerek további veszélyeket hordoznak, kártékony kódokat és biztonsági réseket tartalmazhatnak, ezért a megfelelő felügyelet és ellenőrzés nélkülözhetetlen a biztonsági fenyegetések felismerése és kezelése érdekében. A konténerek futtatása során különös figyelmet kell fordítani a rendszergazdai jogkörökre, a konténerek használata során ezt feltétlenül kerülni kell. Az erőforrások védelmét a docker parancs különböző beállításaival szabályoztuk. Összességében a biztonsági intézkedések foganatosítása a konténer technológia használata esetén is különösen fontos szempont, amely nélkül az informatikai rendszerek stabilitása és integritása nem tartható fenn.

Kérdések, feladatok

  1. Miért kiemelten fontos a konténerek biztonsága?

  2. Milyen operációs rendszerek használhatók a Docker telepítéséhez?

  3. Mi a legnagyobb kockázat, amit a felhasználók ellenőrizetlen konténerei jelenthetnek?

  4. Milyen biztonsági intézkedések szükségesek a konténerek elindítása előtt?

  5. Hogyan okozhat túlzott erőforráshasználatot egy konténer?

  6. Milyen kockázatokat jelenthet az adathozzáférés tekintetében a konténerek indítása?

  7. Miért jelenthetnek biztonsági kockázatot az ismeretlen forrású konténerek?

  8. Miért szükséges a konténerek felügyelete és ellenőrzése?

  9. Hogyan kerülhető el, hogy a konténer alkalmazások rendszergazdai jogkörrel fussanak?

  10. Milyen Docker parancsokkal lehet korlátozni egy konténer erőforrásait?

  11. Milyen paranccsal lehet egy konténert úgy elindítani, hogy a host gép /etc/shadow fájlja helyettesítse a konténerben lévőt?

  12. Hogyan lehet elindítani egy Ubuntu 22.04 alapú konténert úgy, hogy az csak 1 CPU magot és 512M memóriát használhasson?

  13. Milyen parancs használható annak ellenőrzésére, hogy mennyi memória érhető el az egyes konténerek számára?

  14. Milyen Docker parancs segítségével ellenőrizhető egy konténer processzor limitje?