Blogi
Luottamusvirhe: Kuinka monivuokralais-Docker-asetuksemme vuoti tietoja (ja kuinka korjasimme sen)
Opi, miten yhden tiimin naiivi Docker-asetus johti vuokralaisten väliseen tietovuotoon ja kerroksellinen eristysstrategia, joka esti sen.
Yhteenveto
Docker-säiliöt eivät ole oletuksena eristettyjä – ne jakavat isäntäytimen, ja ilman tarkoituksellista konfigurointia vuokralaiset voivat häiritä toisiaan. Tässä artikkelissa käydään läpi todellinen skenaario, jossa monivuokralais-palveluntarjoaja havaitsi, että asiakkaiden säiliöt pääsivät käsiksi toistensa tietokantoihin jaetun verkon ja heikkojen oletusturvallisuusasetusten vuoksi. Näytämme vaiheittaiset muutokset, jotka korjasivat tietovuodon: vuokralaiskohtaiset käyttäjän määrittämät verkot, ei-root-käyttäjät, pudotetut kyvykkyydet, vain luku -tiedostojärjestelmät ja seccomp-profiilit. Yleinen oletus on, että säiliöt tarjoavat luonnostaan vahvan eristyksen; haastamme tämän selittämällä, miksi virtuaalikoneet tarjoavat edelleen kovemman rajan ja milloin harkita hybridilähestymistapaa. Johtopäätös vahvistaa, että eristys on kerroksellinen tehtävä, ei yksittäinen valintaruutu.
Tapaus: Kun säiliöt puhuvat liikaa
Olet asentanut Dockerin yhdelle isännälle useiden asiakasverkkosivustojen ajamiseen. Jokaisella asiakkaalla on oma säiliö – siisti, eristetty ympäristö, eikö niin? Niin mekin ajattelimme. Kunnes rutiiniturvatarkastus paljasti, että Asiakas A:n säiliö luki Asiakas B:n säiliön MySQL-socketia samalla isännällä. Ne jakoivat oletusarvoisen bridge-verkon. Pahempaa, säiliöt toimivat root-käyttäjänä, joten hyökkääjä, joka sai yhden haltuunsa, pystyi peukaloimaan isännän Docker-socketia tai toisen säiliön tiedostojärjestelmää. Tietovuoto ei ollut hienostunut hyökkäys; se oli perusvirhe. Tietoja vuoti. Luottamus katosi.
Epäonnistumisskenaario ei ole harvinainen. Monet tiimit olettavat Dockerin nimiavaruuksien ja cgroupien automaattisesti eristävän vuokralaiset, mutta ne aliarvioivat, kuinka monta pakotietä jää oletuksena avoimeksi. Oletusarvoiset bridge-verkot eivät tarjoa verkkoeristystä säiliöiden välillä. Root-käyttäjänä toimiminen antaa säiliölle enemmän valtaa kuin on tarpeen. Ja ilman selkeitä resurssirajoituksia yksi meluisa naapuri voi näännyttää toiset CPU:sta tai muistista.
Vaihe 1: Lopeta yhden verkon jakaminen
Ensimmäinen korjauksemme oli antaa jokaiselle vuokralaiselle oma käyttäjän määrittämä Docker-verkko. Tämä estää säiliöitä pääsemästä toisiinsa, ellei niitä erikseen yhdistetä. Loimme skriptin, joka jokaiselle vuokralaiselle luo oman verkon ja liittää heidän sovellussäiliönsä siihen. Tietokantasäiliö on samassa vuokralaisverkossa, mutta lisäsimme myös sisäisen verkon vain vuokralaisen sisäiseen viestintään. Ei enää vuokralaisten välistä urkkimista.
Eristimme myös tietokannat ajamalla ne erillisissä säiliöissä samassa vuokralaisverkossa, erillisillä datavolyymeilla. Tämä varmisti, että vaikka hyökkääjä murtautuisi sovellussäiliöön, he eivät voisi nuuskia toisen vuokralaisen tietokantaliikennettä.
Saat syvällisemmän katsauksen verkkoeristysstrategioihin tutustumalla Käytännöllinen Docker-eristysturvallisuuden tarkistuslista monivuokralaisille hostingille.
Vaihe 2: Pudota tarpeettomat oikeudet
Oletuksena Docker-säiliöt toimivat rajoitetulla joukolla Linux-kyvykkyyksiä, mutta niillä on silti enemmän kuin useimmat sovellukset tarvitsevat. Säiliömme toimivat root-käyttäjänä, mikä antoi prosessien sisällä suorittaa toimintoja, kuten tiedostojärjestelmien liittäminen tai ytimen parametrien muuttaminen. Vaihdoimme sovelluksen suorittamisen ei-root-käyttäjänä säiliön sisällä (käyttäen USER-direktiiviä Dockerfilessa) ja pudotimme kaikki kyvykkyydet paitsi ehdottomasti tarvittavat. Tyypilliselle verkkosovellukselle se saattaa olla vain NET_BIND_SERVICE (porttien alle 1024 sitomiseen) ja CHOWN (kirjoittamiseen hakemistoihin). Lisäsimme myös --security-opt no-new-privileges estämään oikeuksien korotusta.
Tämä vaihe yksinään eliminoi monia yleisiä säiliön pakovektoreita. Hyökkääjä, joka saa web-palvelimen haltuunsa, ei voi asentaa paketteja, muokata järjestelmän binäärejä tai päästä isännän Docker-socketiin, koska prosessilta puuttuvat CAP_SYS_ADMIN- tai CAP_DAC_OVERRIDE-kyvykkyydet.
Vaihe 3: Lukitse tiedostojärjestelmä
Kirjoitettavat tiedostojärjestelmät ovat yleinen hyökkäyspinta. Teimme juuritiedostojärjestelmästä vain luku -tilassa (--read-only) kaikille säiliöille ja liitimme väliaikaisia tiedostojärjestelmiä (tmpfs) hakemistoille, jotka tarvitsevat kirjoitusoikeutta, kuten /tmp ja sovelluksen välimuistihakemisto. Tämä estää hyökkääjää muokkaamasta sovelluskoodia tai säilyttämästä haitallisia binäärejä.
Lisäksi käytimme Dockerin --mount-optiota sidontaliitoksiin herkille hakemistoille, kuten Docker-socketille, vain kun se on ehdottoman välttämätöntä – eikä koskaan tuotantosäiliöissä. Periaate: jos säiliön ei tarvitse kirjoittaa polkuun, tee siitä vain luku -tila.
Vaihe 4: Käytä Seccomp- ja AppArmor-profiileja
Oletusarvoiset seccomp-profiilit estävät jo monia vaarallisia järjestelmäkutsuja, mutta räätälöimme niitä edelleen sallimaan vain ne järjestelmäkutsut, joita sovelluksemme todella tarvitsee. Tämä on kompromissi, koska se vaatii sovelluksen profilointia. Yksinkertaisempi lähestymistapa on käyttää Dockerin oletusarvoista seccomp-profiilia ja lisätä --security-opt seccomp=path/to/profile.json, jos tarvitaan tiukempia sääntöjä. Samoin AppArmor-profiilit voivat rajoittaa säiliöprosesseja tiettyihin tiedostopolkuihin ja kyvykkyyksiin. Otimme AppArmorin käyttöön ja käytimme räätälöityä profiilia, joka rajoitti pääsyn vain sovelluksen datahakemistoihin.
Saat kattavan oppaan näistä kovennusvaiheista tutustumalla Docker-säiliöiden kovennus monivuokralaisille hostingille: Vaiheittainen eristysopas.
Vastakkainen näkemys: Joskus tarvitset virtuaalikoneita
Riippumatta siitä, kuinka kovennetut, säiliöt jakavat isäntäytimen. Ytimen haavoittuvuus voi murtaa kaiken eristyksen kerralla. Siksi monet turvallisuustietoiset alustat ajavat säiliöitä kevyiden virtuaalikoneiden sisällä – jokainen vuokralainen saa oman ytimensä. Tämä lisää kustannuksia, mutta tarjoaa laitteistorajapinnan, jota säiliöt yksin eivät pysty. Jos vuokralaisesi käsittelevät luottokorttitietoja tai terveystietoja, hybridilähestymistapa (säiliöt virtuaalikoneiden sisällä) voi olla oikea valinta. Älä oleta, että säiliöeristys on riittävä uhkamallillesi; arvioi tietojen arkaluonteisuus ja sääntelyvaatimukset.
Saat syvällisemmän vertailun eristystasoista lukemalla Monivuokralaisen Docker-arkkitehtuurin suunnittelu: Oikean eristystason valinta.
Johtopäätös: Eristys on pino, ei kytkin
Korjaus ei ollut yksittäinen muutos – se oli kerrostamista: verkkoeristys, rajoitetut oikeudet, vain luku -tiedostojärjestelmät ja järjestelmäkutsujen suodatus. Silloinkin hyväksyimme, että täydellinen eristys on mahdotonta jaettua ydintä käyttävillä säiliöillä. Korkeimman turvallisuuden vuokralaisillemme siirsimme heidät omiin isäntiin. Oppitunti: älä luota oletuksiin. Tarkista Docker-asetuksesi aivan kuin tietovuoto olisi jo tapahtunut. Aika lukita on ennen vuotoa, ei jälkeen.


