Che cosa rende Docker più sicuro di VM o bare metal?

264

Recentemente ho avuto una discussione con un esperto di Docker sulla sicurezza di Docker rispetto alle macchine virtuali. Quando ho detto di aver letto da fonti diverse che è più semplice eseguire il codice all'interno di un contenitore Docker per evaderlo rispetto a un codice in esecuzione su una macchina virtuale, l'esperto ha spiegato che ho torto completamente e che Le macchine Docker sono in realtà più sicure in termini di impedire che il codice dannoso influisca su altre macchine, rispetto a macchine virtuali o bare metal .

Sebbene abbia cercato di spiegare cosa rende i contenitori Docker più sicuri, la sua spiegazione era troppo tecnica per me.

Da quanto ho capito, "la virtualizzazione a livello di sistema operativo riutilizza lo spazio del kernel tra macchine virtuali" come spiegato in una risposta diversa su questo sito. In altre parole, il codice di un contenitore Docker potrebbe sfruttare una vulnerabilità del kernel, che non sarebbe possibile eseguire da una macchina virtuale.

Quindi, cosa potrebbe rendere intrinsecamente più sicuro l'uso di Docker rispetto a VM o isolamento bare metal, in un contesto in cui il codice in esecuzione in un contenitore / macchina proverebbe intenzionalmente a sfuggire e infettare / danneggiare altri contenitori / macchine? Supponiamo che Docker sia configurato correttamente, il che impedisce a tre delle quattro categorie di attacchi descritte qui .

    
posta Arseni Mourzenko 18.09.2017 - 00:08
fonte

9 risposte

425

No, i contenitori Docker non sono più sicuri di una VM.

Citando Daniel Shapira :

In 2017 alone, 434 linux kernel exploits where found, and as you have seen in this post, kernel exploits can be devastating for containerized environments. This is because containers share the same kernel as the host, thus trusting the built-in protection mechanisms alone isn’t sufficient.

1. Exploit del kernel da un contenitore

Se qualcuno sfrutta un bug del kernel all'interno di un contenitore, lo ha sfruttato sul sistema operativo host. Se questo exploit consente l'esecuzione di codice, verrà eseguito sul sistema operativo host, non all'interno del contenitore.

Se questo exploit consente l'accesso arbitrario alla memoria, l'utente malintenzionato può modificare o leggere qualsiasi dato per qualsiasi altro contenitore.

Su una VM, il processo è più lungo: l'utente malintenzionato dovrebbe sfruttare sia il kernel VM, l'hypervisor e il kernel host (e questo potrebbe non essere lo stesso del kernel VM).

2. Inattività di risorse

Poiché tutti i contenitori condividono lo stesso kernel e le stesse risorse, se l'accesso ad alcune risorse non è limitato, un contenitore può usarlo tutto e affamare il sistema operativo host e gli altri contenitori.

Su una VM, le risorse sono definite dall'hypervisor, quindi nessuna VM può negare il SO host da alcuna risorsa, poiché l'hypervisor stesso può essere configurato per fare un uso limitato delle risorse.

3. Scomposizione contenitore

Se un utente all'interno di un contenitore è in grado di uscire dal contenitore utilizzando qualche exploit o configurazione errata, avrà accesso a tutti i contenitori in esecuzione sull'host. Ciò accade perché lo stesso utente che esegue il motore della finestra mobile è l'utente che esegue i contenitori. Se un exploit esegue codice sull'host, verrà eseguito sotto i privilegi del motore di finestra mobile, in modo che possa accedere a qualsiasi contenitore.

4. Separazione dei dati

In un contenitore finestra mobile, ci sono alcune risorse che non sono namespace:

  • SELinux
  • Cgroups
  • file system sotto /sys , /proc/sys ,
  • /proc/sysrq-trigger , /proc/irq , /proc/bus
  • /dev/mem , /dev/sd* file system
  • Moduli kernel

Se un utente malintenzionato può sfruttare uno di questi elementi, sarà il proprietario del sistema operativo host.

Un sistema operativo VM non avrà accesso diretto a nessuno di questi elementi. Parlerà con l'hypervisor e l'hypervisor effettuerà le chiamate di sistema appropriate al sistema operativo host. Filtrerà le chiamate non valide, aggiungendo un livello di sicurezza.

5. Socket non elaborati

Il socket Unix docker predefinito ( /var/run/docker.sock ) può essere montato da qualsiasi contenitore, se non adeguatamente protetto. Se un contenitore monta questo socket, può arrestare, avviare o creare nuove immagini.

Se correttamente configurato e protetto, è possibile raggiungere un elevato livello di sicurezza con un contenitore docker, ma sarà inferiore a una VM configurata correttamente. Indipendentemente da quanti strumenti di protezione siano impiegati, una VM sarà sempre più sicura. L'isolamento del metallo nudo è ancora più sicuro di una VM. Alcune implementazioni bare metal (IBM PR / SM per esempio) possono garantire che le partizioni siano separate come se fossero su hardware separato. Per quanto ne so, non c'è modo di sfuggire a una virtualizzazione PR / SM.

    
risposta data 18.09.2017 - 04:13
fonte
73

Dire che una VM o un Docker è più sicuro dell'altro è una massiccia semplificazione.

VM fornisce la virtualizzazione dell'hardware; l'hypervisor emula l'hardware in modo che il kernel guest pensi che sia in esecuzione sul proprio computer. Questo tipo di virtualizzazione è più facile da isolare gli uni dagli altri. Se la preoccupazione principale per la virtualizzazione è l'isolamento (non è proprio necessario che le macchine virtuali interagiscano l'una con l'altra), allora VM sarà notevolmente più semplice da proteggere.

Docker fornisce la virtualizzazione del kernel / sistema operativo e Docker utilizza gli spazi dei nomi del kernel per virtualizzare il kernel e il sistema operativo in modo che l'ospite pensi che sia in esecuzione sulla propria istanza del sistema operativo. La virtualizzazione del sistema operativo offre una flessibilità notevolmente maggiore su come proteggere l'interconnessione tra i contenitori. Se la tua preoccupazione principale per la virtualizzazione richiede di interconnettere i contenitori, Docker offre la possibilità di definire queste regole di condivisione in modi che sono impossibili o troppo ingombranti con le macchine virtuali.

La grande flessibilità comporta grandi rischi; è più semplice configurare erroneamente la finestra mobile rispetto alla VM e la flessibilità della condivisione delle risorse della finestra mobile crea anche maggiori opportunità sia per l'implementazione che per i bug di configurazione. Tuttavia, se si riesce a configurare correttamente le autorizzazioni di condivisione e si presuppone che non vi siano bug di implementazione in Docker o nel kernel, Docker offre una condivisione molto più dettagliata della virtualizzazione dell'hardware e può offrire una sicurezza generale migliore.

Ad esempio, la condivisione del socket. Con Docker, puoi creare facilmente un socket con nome condiviso tra due contenitori condividendo il file socket e puoi definire le autorizzazioni di sicurezza (utilizzando qualsiasi modulo di sicurezza esistente: autorizzazione Unix tradizionale, capacità, SELinux, AppArmor, seccomp, ecc.) Tra endpoint del socket in modo che la finestra mobile / il kernel impone quali e come le applicazioni possono accedere agli endpoint del socket. Con una macchina virtuale, è possibile condividere un socket un po 'più ingombrante impostando una catena di socket per inviare dati al socket tramite TCP. Tuttavia, l'hypervisor ha una visibilità molto limitata e non c'è modo di controllare l'accesso agli endpoint del socket, poiché le autorizzazioni per questi end point del socket vengono applicate dai kernel guest.

Un altro esempio è la condivisione di cartelle. Con i contenitori, è possibile condividere una cartella impostando una montatura condivisa e, poiché Docker / kernel applica le autorizzazioni dei file utilizzate dai contenitori, il sistema guest non può ignorare tali restrizioni. Con una VM, se si desidera condividere la cartella, è necessario lasciare che una macchina esegua un file server di rete o un server Samba o un server FTP e l'hypervisor abbia poca visibilità nella condivisione e non possa imporre le autorizzazioni di condivisione. Le parti mobili aggiuntive qui (il file server), possono anche avere le proprie vulnerabilità e problemi di errata configurazione da considerare.

TL; DR: Usa VM per l'isolamento e contenitori per la condivisione controllata.

    
risposta data 18.09.2017 - 03:39
fonte
23

Come hai giustamente affermato, Docker usa "Virtualizzazione a livello di sistema operativo". Puoi pensare a questo (se sei un fan * nix) come una forma elaborata di chroot .

Sfruttando le funzionalità e le funzionalità integrate nel sistema operativo, Docker funge da direttore per i contenitori. La vista del software del sistema operativo è dettata da Docker.

Lo stesso kernel viene utilizzato su tutti i contenitori. Quindi, ad esempio, se sono in grado di causare un panico del kernel in un contenitore (si pensi a "Blue Screen of Death"), tutti gli altri contenitori sono interessati .

La configurazione sembra essere molto più critica rispetto alle soluzioni basate su hardware. Tutto è nello stesso spazio condiviso in modo efficace. Immagina di mettere un predatore selvaggio accanto alla fonte di cibo naturale. Se non hai messo un recinto abbastanza strong intorno al predatore, o hai dimenticato di chiudere il cancello ogni volta che hai lasciato il recinto, puoi probabilmente immaginare cosa succederebbe.

Pur essendo certamente una soluzione leggera, non avrei sicuramente eseguito alcun codice sconosciuto accanto a quello del codice attendibile.

Il codice dannoso dovrebbe determinare un modo per estendere i suoi privilegi a un livello root / amministratore in modo da sfuggire al contenitore in modo significativo.

In una macchina virtuale, l'hypervisor verrebbe attaccato, non il kernel. Ciò potrebbe rivelarsi più sicuro in quanto esiste un livello più elevato di isolamento tra "contenitori", ma introduce un overhead superiore per la gestione.

Da quanto ho capito, non c'è nulla che rende Docker più sicuro di "bare metal" o soluzioni basate sull'hardware. Sarei propenso a dire che Docker è meno sicuro. In termini di 1 contenitore per un pezzo di software, ciò può provare una storia diversa.

Se non sei sicuro degli esempi del mondo reale, darei un'occhiata a OpenVZ. Utilizza la virtualizzazione a livello di sistema operativo in uno stile simile proprio come Docker, ma con un kernel modificato.

    
risposta data 18.09.2017 - 02:49
fonte
11

I contenitori di Docker non sono intrinsecamente "Più sicuri" Ma la capacità di duplicare rapidamente e distruggere i duplicati in un cluster è molto utile da un punto di vista della sicurezza.

Ok, molte altre risposte qui, ma le persone tendono a dimenticare che a volte lo strumento migliore che si può usare per proteggere un server web / applicazione è la possibilità di ridistribuire rapidamente il codice pulito dopo che il codice già installato è stato compromesso.

Niente al mondo sicuro al 100% o sicuro. Soprattutto nel mondo delle applicazioni web esposte. Ma Docker consente pratiche migliori se le persone capiscono il loro valore e si impegnano in quelle pratiche .

  • Effettua backup regolari di risorse e database.
  • Disponi sempre di una configurazione solida e portatile.
  • Gestisci il codice in un repository di codice.
  • Utilizza un processo di distribuzione che consente la ridistribuzione del codice in poche sequenze di tasti.
  • E utilizzare uno strumento di configurazione del sistema per garantire che i sistemi / server possano essere rapidamente ricreati con il minimo sforzo.
  • Se possibile, distribuisci il tuo codice in una specie di cluster con bilanciamento del carico, in modo che se un codice di "cosa" venga compromesso, puoi eliminarlo senza far cadere completamente l'app.

La finestra mobile si inserisce nell'ultimo punto. Così fanno le macchine virtuali, ma Docker fa ancora più fatica perché una volta presa la decisione di usare Docker, si utilizza intrinsecamente uno strumento la cui mentalità / mentalità è: "Non durerò per sempre. Ho bisogno di essere ricreato. "

E nei casi di container Docker infetto, puoi portarlo offline, per quanto riguarda il mondo esterno, per fare qualche analisi forense per vedere cosa è successo e vedere cosa può essere fatto per ridistribuire il codice in sicurezza ad altri esistenti e la nuova base di codice viene installata all'interno dei contenitori Docker.

Le macchine virtuali potrebbero essere in grado di essere utilizzate in questo modo, ma nella mia pratica ed esperienza solo gli sviluppatori pensano davvero in questo modo sulle VM. La maggior parte degli amministratori di sistema - e dei team di cui fanno parte - vedono le VM come un modo per spremere più facilmente l'utilizzo e l'utilità da un server bare metal piuttosto che vederle come macchine monouso che possono essere ricreate per capriccio. p>

Con Docker devi davvero fare di tutto per rendere un container Docker un monolite non monouso. Docker è uno strumento per sviluppatori di applicazioni creato per un'epoca in cui la virtualizzazione è rapida, economica e facile. E quando viene distribuito in una sorta di cluster con bilanciamento del carico, si ottiene la stabilità aggiunta di tempi di inattività minimi o nulli.

    
risposta data 22.09.2017 - 15:55
fonte
10

Sono d'accordo con la risposta di ThoriumBR se stiamo solo confrontando una VM vuota con un contenitore Docker vuoto. Va notato, tuttavia, che la corretta configurazione del sistema come in Red Hat's Host atomico attenua molti di questi fattori e ne elimina anche alcuni.

Inoltre, da quando è stato avviato Docker, puoi contare su un lato il numero dei tipi di vulnerabilità menzionati nella sua risposta, i quali potrebbero essere mitigati da ulteriori livelli come SELinux . Stiamo anche iniziando a vedere i runtime compatibili con OCI basati su hypervisor, che puoi utilizzare al posto di runc se sei davvero paranoico e sei disposto a subire un calo di prestazioni.

Farò inoltre notare che la maggior parte delle vulnerabilità nel software non sono nello spazio kernel / driver in cui le VM hanno il vantaggio di sicurezza, ma nel livello application , dove i container Docker hanno il vantaggio , perché rendono più facile creare superfici di attacco a processo singolo. È possibile creare un contenitore Docker utilizzabile con un singolo eseguibile collegato in modo statico che viene eseguito come utente non root, con risorse e funzionalità limitate. Non è possibile creare una VM con una superficie di attacco così piccola.

La linea di fondo è che devi guardare l'intera immagine di sicurezza. I contenitori Docker possono essere molto sicuri, ma è necessario esaminare l'intera catena di fornitura del software e assicurarsi di configurare correttamente la finestra mobile e l'host. Le macchine virtuali hanno il loro insieme di punti di forza e di debolezza. Non puoi semplicemente confrontare i due "out of the box" e prendere una decisione. È necessario un processo per rafforzare la soluzione.

    
risposta data 19.09.2017 - 15:13
fonte
6

Nel livello applicazione, sì

La domanda è troppo ampia per poter rispondere con un semplice "sì" o "no".

Ci sono superfici di attacco molto chiare e aperte per i contenitori Docker:

  • Se l'attaccante è colui che può avviare contenitori (ad esempio, ha accesso all'API Docker), quindi immediatamente, senza ulteriore azione, ha accesso completo root all'host. Questo è ben noto da anni, è stato dimostrato, e non è oggetto di discussione da parte di nessuno (Google o SE ti forniranno immediatamente semplici linee di comando che non permettono nemmeno a un particolare contenitore di funzionare).
  • Se l'attaccante riesce a ottenere root all'interno del contenitore, allora sei nei guai. In effetti, può quindi effettuare chiamate al kernel abbastanza arbitrarie e provare a influenzare il kernel dell'host. Sfortunatamente, molte immagini docker sembrano eseguire le loro cose come root e saltare USER nel Dockerfile - questo non è un problema Docker ma un problema utente.

Vedo uno scenario che effettivamente renderebbe un sistema basato su immagini Docker più sicuro (forse ...):

  • Se le tue immagini sono religiose il meno possibile e solo una per preoccupazione.
  • E tutti funzionano senza privilegi (cioè senza --privileged e non come root ).
  • E il networking è il più stretto possibile.

Quindi probabilmente sarebbe più sicuro di una soluzione VM con i seguenti parametri:

  • Base installata più piccola possibile.
  • Molte preoccupazioni installate nella stessa VM.
  • Networking il più stretto possibile

La ragione è che se, ad esempio, un server HTTP è in corso, ed è in esecuzione all'interno di un contenitore minimale (e qui intendo "minimo" qui - cioè, alpine con niente eccetto il minimo indispensabile, incluso nessun networking in uscita, nessun volume rw ecc.), quindi ci sono meno possibilità che l'hacker possa fare qualcosa se non fosse una VM con altri servizi in esecuzione.

Ovviamente, questo scenario presuppone che le macchine virtuali siano effettivamente più grasse dei contenitori. Se rendi le VM uguali ai container, allora è un punto controverso. Ma poi, uno scenario Docker ben progettato sarebbe progettato in questo modo. E una normale configurazione VM sarebbe forse, almeno nel tempo, migrare a un numero sempre maggiore di roba in fase di installazione.

    
risposta data 21.09.2017 - 13:47
fonte
2

Ci sono già alcune grandi risposte, ma per avere una spiegazione completa della differenza tra docker e VM aggiungerò un'immagine:

Source

Da quella prospettiva è più facile capire perché VM sia più sicura del contenitore Docker.

    
risposta data 29.09.2017 - 06:32
fonte
1

Il principale punto di forza del docker non è essere più sicuro, ma più facile. Questo include:

  • Predefiniti utili, incluse alcune opzioni di sicurezza.
  • Non funziona con la configurazione di LXC, cgroup e così via.
  • Immagini pronte che possono essere scaricate con una sola riga.
  • VM riproducibili. Non ci sono più argomenti "lavora sulla mia macchina".

La finestra mobile è sicura quanto le tecniche che sta utilizzando, che sono principalmente LXC (spazi dei nomi linux), selinux e apparmor.

L'uso della finestra mobile è spesso orribilmente insicuro. Le persone usano una linea per scaricare un'immagine fatta da qualcuno, non hanno nemmeno mai letto il nome prima di eseguire il contenitore del suo sistema operativo. Anche quando costruisci l'immagine tu stesso da una propria baseimage (facile da creare con debootstrap come quando stai costruendo un chroot) e un Dockerfile, spesso include il curl $URL|bash anti-pattern per installare il software nel contenitore.

L'altra cosa è che "il modo docker" non è quello di aggiornare le immagini, ma di ricostruirle. Questo significa fermare (mentre le persone spesso presumono che tu abbia un failover in esecuzione con la nuova immagine), ricostruire e ricominciare.

Questo deriva dal modo in cui vengono create le istantanee, dove una solita apt-get dist-upgrade introduce livelli che sono semanticamente rumore dal punto di vista della finestra mobile, dove la cronologia dovrebbe apparire come "baseimage, aggiunto apache, php aggiunto, roundcube installato" senza "aggiornamento apt-get giornaliero" tra i passaggi.

Se stai mantenendo un proprio repository di immagini nella tua LAN, la finestra mobile può essere molto utile, poiché puoi ridistribuire rapidamente le immagini aggiornate.

La funzione di istantanea è un'altra cosa che può essere un buon miglioramento della sicurezza, quando puoi eseguire rapidamente il rollback o il fork di un'immagine per provare qualcosa di nuovo in un ambiente di test.

La linea di fondo è che la finestra mobile è uno strumento molto utile per gli sviluppatori, che vogliono testare la distribuzione del loro codice riproducibile e senza cambiare il loro sistema operativo installato, ma ci sono soluzioni migliori per le produzioni. Quindi puoi eseguire la finestra mobile in produzione in modo sicuro, ma non rende le cose più sicure di una buona configurazione LXC senza finestra mobile.

Per quanto ne so non sono limitati a LXC come loro VM o non saranno limitati presto, specialmente quando sono indirizzati anche a Windows. La scelta di un altro back-end ha implicazioni sulla sicurezza, che sono le stesse di LXC contro KVM vs VirtualBox. Gli altri punti rimarranno probabilmente uguali.

    
risposta data 27.09.2017 - 16:11
fonte
0

Per prima cosa vorrei sottolineare che più riutilizzi / condividi le stesse risorse più duramente è tenerlo al sicuro.

Detto questo, Docker tenta di eseguire ogni processo su una sandbox (Container) e questo è l'unico motivo per cui la finestra mobile può essere considerata più sicura. Dal processo multiplo eseguito dal tuo server, avrai teoricamente accesso al tuo processo ed esporrai una cartella condivisa o un socket all'altro processo. I file di configurazione, le credenziali, i segreti altre porte / prese di manutenzione e di debug non saranno accessibili nemmeno dalla stessa "macchina".

Docker ci si sente più sicuro in quanto il modo è stato progettato per funzionare: sandbox ogni processo in esecuzione. Dove Virtual Machines e Baremetal eseguono sandbox in un gruppo di processi e applicazioni e tra loro è responsabilità dell'utente impostare le autorizzazioni di conseguenza.

    
risposta data 29.09.2017 - 11:10
fonte

Leggi altre domande sui tag