Blog

Mýtus dôvery: Ako náš multi-tenant Docker setup unikal údaje (a ako sme to opravili)

Zistite, ako naivné nastavenie Dockeru v jednom tíme viedlo k úniku údajov medzi tenantmi a aká stratifikovaná izolačná stratégia tomu zabránila.

Súhrn

Docker kontajnery nie sú štandardne izolované – zdieľajú jadro hostiteľa a bez zámernej konfigurácie môžu tenanty navzájom interferovať. Tento článok popisuje reálny scenár, v ktorom multi-tenant hostingový poskytovateľ zistil, že klientske kontajnery môžu pristupovať k databázam iných klientov kvôli zdieľanej sieti a slabým bezpečnostným predvoleniam. Ukazujeme krok za krokom zmeny, ktoré opravili únik: používateľom definované siete pre jednotlivých tenantov, ne-root používatelia, odobraté schopnosti, súborové systémy len na čítanie a profily seccomp. Bežným predpokladom je, že kontajnery prirodzene poskytujú silnú izoláciu; spochybňujeme to vysvetlením, prečo VM stále ponúkajú pevnejšiu hranicu a kedy zvážiť hybridný prístup. Záver zdôrazňuje, že izolácia je vrstvené cvičenie, nie jediné zaškrtávacie políčko.

Incident: Keď kontajnery príliš veľa hovoria

Nastavili ste Docker na jednom hostiteľovi na spustenie viacerých klientov. Každý klient má svoj vlastný kontajner – úhľadné, izolované prostredie, však? To sme si mysleli aj my. Kým bežný bezpečnostný audit neodhalil, že kontajner Klienta A čítal MySQL socket kontajnera Klienta B na tom istom hostiteľovi. Zdieľali predvolenú sieť bridge. Horšie bolo, že kontajnery bežali ako root, takže útočník, ktorý kompromitoval jeden, mohol manipulovať s Docker socketom hostiteľa alebo súborovým systémom iného kontajnera. Únik nebol sofistikovaný exploit; bola to základná nesprávna konfigurácia. Dátum unikol. Dôvera sa rozplynula.

Scenár zlyhania nie je nezvyčajný. Mnoho tímov predpokladá, že Docker menné priestory a cgroups automaticky oddelia tenantov, ale podceňujú, koľko únikových ciest zostáva štandardne otvorených. Predvolené bridge siete neponúkajú žiadnu sieťovú izoláciu medzi kontajnermi. Beh ako root dáva kontajneru viac moci, než je potrebné. A bez explicitných limitov zdrojov môže jeden hlučný sused pripraviť ostatné o CPU alebo pamäť.

Krok 1: Prestaňte zdieľať jednu sieť

Našou prvou opravou bolo poskytnúť každému tenantovi jeho vlastnú používateľsky definovanú Docker sieť. To zabraňuje kontajnerom vzájomne sa dosahovať, pokiaľ ich explicitne nepripojíte. Vytvorili sme skript, ktorý pre každého tenanta vytvorí vyhradenú sieť a pripojí k nej kontajner aplikácie. Databázový kontajner žije v rovnakej sieti tenanta, ale pridali sme aj internú sieť len pre komunikáciu v rámci tenanta. Žiadne viac vnikania medzi tenantmi.

Taktiež sme izolovali databázy tým, že sme ich spustili v samostatných kontajneroch na rovnakej sieti tenanta s oddelenými dátovými zväzkami. To zabezpečilo, že aj keby sa útočník dostal do kontajnera aplikácie, nemohol by odpočúvať databázovú prevádzku iného tenanta.

Pre hlbší ponor do stratégií izolácie sietí si pozrite Praktický kontrolný zoznam izolácie Dockeru pre multi-tenant hosting.

Krok 2: Odstráňte nepotrebné oprávnenia

Štandardne Docker kontajnery bežia s obmedzenou sadou Linux schopností, ale stále majú viac, než väčšina aplikácií potrebuje. Naše kontajnery bežali ako root, čo umožňovalo procesom v nich vykonávať akcie ako pripájanie súborových systémov alebo zmenu parametrov jadra. Prešli sme na spúšťanie aplikácie ako ne-root používateľ v kontajneri (pomocou direktívy USER v Dockerfile) a odstránili sme všetky schopnosti okrem tých, ktoré sú absolútne nevyhnutné. Pre typickú webovú aplikáciu to môžu byť iba NET_BIND_SERVICE (pre viazanie na porty pod 1024) a CHOWN (pre zápis do adresárov). Tiež sme pridali --security-opt no-new-privileges na zabránenie eskalácii oprávnení.

Tento krok sám o sebe eliminoval mnoho bežných vektorov úniku z kontajnera. Útočník, ktorý kompromituje webový server, nemôže inštalovať balíky, upravovať systémové binárky ani pristupovať k Docker socketu hostiteľa, pretože procesu chýbajú schopnosti CAP_SYS_ADMIN alebo CAP_DAC_OVERRIDE.

Krok 3: Uzamknite súborový systém

Zapisovateľné súborové systémy sú bežným útočným povrchom. Spravili sme koreňový súborový systém len na čítanie (--read-only) pre všetky kontajnery a potom sme pripojili dočasné súborové systémy (tmpfs) pre adresáre, ktoré potrebujú zápis, ako /tmp a adresár vyrovnávacej pamäte aplikácie. To bráni útočníkovi v úprave kódu aplikácie alebo v uchovávaní škodlivých binárok.

Okrem toho sme použili voľbu --mount na viazanie citlivých adresárov, ako je Docker socket, len keď je to absolútne nevyhnutné – a nikdy na produkčných kontajneroch. Princíp: ak kontajner nemusí zapisovať do cesty, urobte ju len na čítanie.

Krok 4: Aplikujte profily Seccomp a AppArmor

Predvolené profily seccomp už blokujú mnoho nebezpečných systémových volaní, ale my sme ich ďalej prispôsobili, aby povoľovali len tie systémové volania, ktoré aplikácia skutočne potrebuje. Toto je kompromis, pretože vyžaduje profilovanie aplikácie. Jednoduchší prístup je použiť predvolený profil seccomp Dockeru a potom pridať --security-opt seccomp=cesta/k/profilu.json, ak potrebujete prísnejšie pravidlá. Podobne profily AppArmor môžu obmedziť procesy kontajnera na konkrétne cesty a schopnosti. Povolili sme AppArmor a použili vlastný profil, ktorý obmedzil prístup len na dátové adresáre aplikácie.

Pre komplexného sprievodcu týmito krokmi posilnenia odporúčame Zosilnenie Docker kontajnerov pre multi-tenant hosting: Sprievodca izoláciou krok za krokom.

Kontroverzný názor: Niekedy potrebujete VM

Bez ohľadu na to, ako sú kontajnery posilnené, zdieľajú jadro hostiteľa. Zraniteľnosť jadra môže naraz prelomiť všetku izoláciu. Preto mnoho bezpečnostne uvedomelých platforiem spúšťa kontajnery v rámci ľahkých VM – každý tenant má svoje vlastné jadro. To prináša réžiu, ale poskytuje hranicu na úrovni hardvéru, ktorú samotné kontajnery nemôžu dosiahnuť. Ak vaši tenantí spracúvajú údaje o kreditných kartách alebo zdravotné záznamy, hybridný prístup (kontajnery v rámci VM) môže byť správnou voľbou. Nepredpokladajte, že izolácia kontajnerov je dostatočná pre váš model hrozieb; vyhodnoťte citlivosť údajov a regulačné požiadavky.

Pre hlbšie porovnanie úrovní izolácie si prečítajte Navrhovanie multi-tenant Docker architektúry: Výber správnej úrovne izolácie.

Záver: Izolácia je stack, nie prepínač

Oprava nebola jediná zmena – bolo to vrstvenie: sieťová izolácia, obmedzené oprávnenia, súborové systémy len na čítanie a filtrovanie systémových volaní. Aj potom sme akceptovali, že dokonalá izolácia je s kontajnermi zdieľajúcimi jadro nemožná. Pre našich najviac zabezpečených tenantov sme ich presunuli na vyhradené hostitele. Poučenie: neverte žiadnemu predvolenému nastaveniu. Auditujte svoje Docker nastavenie, ako keby už došlo k úniku. Čas na uzamknutie je pred únikom, nie po ňom.

Sources (5)