Container Linux e VM: un confronto di sicurezza

Gli sviluppatori adorano i contenitori. Sono facili da usare e veloci da avviare. Puoi eseguirne molti anche su hardware semplice. Il sovraccarico di avvio è sempre stato una rovina per lo sviluppo e il test e questo sovraccarico aumenta solo con le architetture di microservizi. Se uno sviluppatore ha bisogno di una mezza dozzina di servizi, potrebbe facilmente sprecare un giorno o due con l'installazione: configurazione dell'hardware, esecuzione di programmi di installazione, lotta alle incompatibilità.

Con i contenitori, che si riducono a minuti o secondi e possono essere eseguiti su una workstation di sviluppo. I repository prontamente disponibili di utili immagini di contenitori moltiplicano la produttività degli sviluppatori, proprio come fa l'open source, ma senza il problema di fare una build. I team operativi sono stati più lenti nell'adozione dei container. Uno dei motivi è che molte applicazioni che devono supportare non sono ancora containerizzate. Un altro motivo è la riluttanza ad allontanarsi dalle VM.

Per gli operatori, il passaggio dal bare metal alle VM è stato naturale. Le singole VM hanno l'aspetto e possono essere gestite come sistemi individuali, utilizzando gli stessi strumenti e processi. Le prime preoccupazioni sulla sicurezza delle VM sono state dissipate dalla lunga storia di produzione delle VM nel mondo mainframe, dalla capacità di applicare gli stessi controlli utilizzati per i sistemi bare metal, dal supporto della virtualizzazione hardware e dalla maturità in evoluzione degli strumenti di gestione delle VM.

Molte delle prime preoccupazioni sulla sicurezza si riducevano a una domanda: le VM erano sicure come il bare metal? Ora vengono sollevate domande simili sui contenitori. Quanto sono sicuri i container e come si confrontano con le VM? Certamente se confrontiamo i servizi in esecuzione in container con gli stessi servizi in esecuzione come processi separati sullo stesso sistema, la versione container è più sicura. La separazione fornita dagli spazi dei nomi Linux e dai cgroup fornisce barriere che non esistono tra i processi semplici. Il confronto con le VM è meno netto. Diamo uno sguardo alle VM e ai container dal punto di vista della sicurezza.

In questo articolo, prenderò due diversi approcci per confrontare la sicurezza della VM e del contenitore. Il primo approccio sarà più strutturale o teorico, esaminando le caratteristiche di ciascuno da una prospettiva di sicurezza. Quindi applicherò un'analisi più pratica osservando cosa accade in una tipica violazione e come potrebbe essere influenzata dalle architetture di container e VM.

Vista strutturale

Per l'approccio strutturale confronterò la superficie di attacco di entrambi i sistemi. Una superficie di attacco rappresenta il numero di punti in cui un sistema può essere attaccato. Non è definito con precisione (come un numero, ad esempio) ma è utile per i confronti. Per uno scassinatore, una casa con 10 porte ha una superficie di attacco maggiore di una casa con una porta, anche se le porte sono identiche. Una porta potrebbe essere lasciata aperta; una serratura potrebbe essere difettosa; porte in luoghi diversi potrebbero offrire maggiore privacy a un intruso e così via.

Nei sistemi informatici, la superficie di attacco include tutto ciò in cui l'aggressore (o il software che agisce per suo conto) può "toccare" il sistema di destinazione. Interfacce di rete, connessioni hardware e risorse condivise sono tutti i possibili punti di attacco. Tieni presente che la superficie di attacco non implica che esista una vera vulnerabilità. Tutte e 10 le porte potrebbero essere perfettamente sicure. Ma una superficie di attacco più ampia significa più posti da proteggere e maggiore è la probabilità che l'aggressore trovi un punto debole in almeno uno.

La superficie di attacco totale dipende dal numero di diversi punti di contatto e dalla complessità di ciascuno. Diamo un'occhiata a un semplice esempio. Immagina un sistema vecchio stile che fornisce quotazioni di borsa. Ha un'unica interfaccia, una semplice linea seriale. Anche il protocollo su quella riga è semplice: un simbolo di borsa di lunghezza fissa, diciamo cinque caratteri, viene inviato al server, che risponde con una quotazione di prezzo di lunghezza fissa, diciamo 10 caratteri. Non ci sono Ethernet, TCP / IP, HTTP e così via. (In realtà ho lavorato su tali sistemi molto tempo fa in una galassia molto, molto lontana.)

La superficie di attacco di questo sistema è molto piccola. L'aggressore può manipolare le caratteristiche elettriche della linea seriale, inviare simboli errati, inviare troppi dati o comunque variare il protocollo. La protezione del sistema implicherebbe l'implementazione di controlli appropriati contro tali attacchi.

Ora immagina lo stesso servizio, ma in un'architettura moderna. Il servizio è disponibile su Internet ed espone un'API RESTful. Il lato elettrico dell'attacco è sparito: tutto ciò che farà è friggere il router o lo switch dell'attaccante. Ma il protocollo è enormemente più complesso. Dispone di livelli per IP, TCP, eventualmente TLS e HTTP, ognuno dei quali offre la possibilità di una vulnerabilità sfruttabile. Il sistema moderno ha una superficie di attacco molto più ampia, anche se sembra ancora all'attaccante come un unico punto di interfaccia.

Superficie di attacco in metallo nudo

Per un utente malintenzionato non fisicamente presente nel data center, la superficie di attacco iniziale è la rete nel server. Ciò ha portato alla "vista perimetrale" della sicurezza: proteggere i punti di ingresso nel data center e nulla può entrare. Se l'aggressore non riesce a entrare, non importa cosa succede tra i sistemi all'interno. Ha funzionato bene quando le interfacce perimetrali erano semplici (si pensi al dial-up), ma ha favorito i punti deboli sulle interfacce interne. Gli aggressori che hanno trovato un buco nel perimetro scoprivano spesso che la superficie di attacco interna della server farm era molto più grande di quella esterna e potevano causare danni considerevoli una volta all'interno.

Questa superficie di attacco interna includeva connessioni di rete tra i server ma anche interazioni da processo a processo all'interno di un singolo server. Peggio ancora, dal momento che molti servizi vengono eseguiti con privilegi elevati (utente "root"), entrare con successo in uno significherebbe effettivamente accesso illimitato a qualsiasi altra cosa su quel sistema, senza dover cercare ulteriori vulnerabilità. Un intero settore è cresciuto intorno alla protezione dei server - firewall, antimalware, rilevamento delle intrusioni e così via - con risultati tutt'altro che perfetti.

Ci sono anche interessanti attacchi “side channel” contro i server. I ricercatori hanno mostrato esempi di utilizzo del consumo energetico, del rumore o delle radiazioni elettromagnetiche dai computer per estrarre informazioni, a volte dati molto sensibili come le chiavi crittografiche. Altri attacchi hanno sfruttato interfacce esposte come i protocolli della tastiera wireless. In generale, tuttavia, questi attacchi sono più difficili - potrebbero richiedere la vicinanza al server, ad esempio - quindi il percorso principale per arrivare "in rete" è più comune.

Superficie di attacco VM

Quando le VM vengono utilizzate allo stesso modo del bare metal, senza alcuna differenza nell'architettura dell'applicazione (come spesso accade), condividono la maggior parte degli stessi punti di attacco. Un'ulteriore superficie di attacco è il potenziale errore dell'hypervisor, del sistema operativo o dell'hardware per isolare correttamente le risorse tra le VM, consentendo a una VM di leggere in qualche modo la memoria di un'altra VM. Anche l'interfaccia tra la VM e l'hypervisor rappresenta un punto di attacco. Se una VM può sfondare e ottenere codice arbitrario in esecuzione nell'hypervisor, può accedere ad altre VM sullo stesso sistema. Lo stesso hypervisor rappresenta un punto di attacco poiché espone le interfacce di gestione.

Esistono punti di attacco aggiuntivi a seconda del tipo di sistema VM. I sistemi VM di tipo 2 utilizzano un hypervisor in esecuzione come processo su un sistema operativo host sottostante. Questi sistemi possono essere attaccati attaccando il sistema operativo host. Se l'aggressore riesce a ottenere codice in esecuzione sul sistema host, può potenzialmente influenzare l'hypervisor e le VM, soprattutto se può ottenere l'accesso come utente privilegiato. La presenza di un intero sistema operativo, incluse utilità, strumenti di gestione e possibilmente altri servizi e punti di ingresso (come SSH) fornisce una serie di possibili punti di attacco. I sistemi VM di tipo 1, in cui l'hypervisor viene eseguito direttamente sull'hardware sottostante, eliminano questi punti di ingresso e quindi hanno una superficie di attacco inferiore.

Superficie di attacco del contenitore

Come con le VM, i container condividono i punti di attacco fondamentali di accesso alla rete dei sistemi bare metal. Inoltre, come le macchine virtuali di tipo 2, i sistemi container che utilizzano un sistema operativo host "completamente caricato" sono soggetti a tutti gli stessi attacchi disponibili contro le utilità e i servizi di quel sistema operativo host. Se l'attaccante può ottenere l'accesso a quell'host, può provare ad accedere o influenzare in altro modo i container in esecuzione. Se ottiene un accesso privilegiato ("root"), l'aggressore sarà in grado di accedere o controllare qualsiasi contenitore. Un sistema operativo "minimalista" (come KurmaOS di Apcera) può aiutare a ridurre questa superficie di attacco ma non può eliminarla del tutto, poiché per la gestione dei container è richiesto un certo accesso al sistema operativo host.

Anche i meccanismi di base della separazione dei contenitori (spazi dei nomi) offrono potenziali punti di attacco. Inoltre, non tutti gli aspetti dei processi sui sistemi Linux hanno spazi dei nomi, quindi alcuni elementi sono condivisi tra i contenitori. Queste sono aree naturali che gli aggressori devono sondare. Infine, il processo all'interfaccia del kernel (per le chiamate di sistema) è grande ed esposto in ogni contenitore, a differenza dell'interfaccia molto più piccola tra una VM e l'hypervisor. Le vulnerabilità nelle chiamate di sistema possono offrire un potenziale accesso al kernel. Un esempio di ciò è la vulnerabilità segnalata di recente nel portachiavi di Linux.

Considerazioni architettoniche

Sia per le VM che per i contenitori, la dimensione della superficie di attacco può essere influenzata dall'architettura dell'applicazione e dal modo in cui viene utilizzata la tecnologia.

Molte applicazioni VM legacy trattano le VM come bare metal. In altre parole, non hanno adattato le loro architetture in modo specifico per le VM o per i modelli di sicurezza non basati sulla sicurezza perimetrale. Potrebbero installare molti servizi sulla stessa VM, eseguire i servizi con privilegi di root e avere pochi o nessun controllo di sicurezza tra i servizi. La riprogettazione di queste applicazioni (o più probabilmente la loro sostituzione con altre più nuove) potrebbe utilizzare le VM per fornire la separazione di sicurezza tra le unità funzionali, piuttosto che semplicemente come mezzo per gestire un numero maggiore di macchine.

I contenitori sono adatti per architetture di microservizi che "mettono insieme" un gran numero di servizi (in genere) piccoli utilizzando API standardizzate. Tali servizi hanno spesso una durata molto breve, in cui un servizio containerizzato viene avviato su richiesta, risponde a una richiesta e viene distrutto o in cui i servizi vengono rapidamente aumentati e diminuiti in base alla domanda. Tale modello di utilizzo dipende dalla rapida creazione di istanze supportata dai contenitori. Dal punto di vista della sicurezza ha sia vantaggi che svantaggi.

Il maggior numero di servizi significa un maggior numero di interfacce di rete e quindi una maggiore superficie di attacco. Tuttavia, consente anche più controlli a livello di rete. Ad esempio, nella piattaforma Apcera, tutto il traffico da container a container deve essere esplicitamente consentito. Un contenitore non autorizzato non può raggiungere arbitrariamente alcun endpoint di rete.

La durata breve del contenitore significa che se un utente malintenzionato entra, il tempo a disposizione per fare qualcosa è limitato, a differenza della finestra di opportunità offerta da un servizio di lunga durata. Lo svantaggio è che la scientifica è più difficile. Una volta che il contenitore è stato rimosso, non può essere rilevato ed esaminato per trovare il malware. Queste architetture rendono anche più difficile per un utente malintenzionato installare malware che sopravvive alla distruzione del container, come potrebbe fare su bare metal installando un driver che viene caricato all'avvio. I contenitori vengono generalmente caricati da un repository attendibile di sola lettura e possono essere ulteriormente protetti da controlli crittografici.

Consideriamo ora cosa succede durante una violazione.

Protezione contro le violazioni

Gli aggressori hanno in genere uno o due obiettivi per penetrare in un sistema server. Vogliono ottenere dati o fare danni.

Se sono alla ricerca di dati, vogliono infiltrarsi nel maggior numero di sistemi possibile, con i privilegi più elevati possibili e mantenere tale accesso il più a lungo possibile. Raggiungere questo obiettivo dà loro il tempo di trovare i dati, che potrebbero essere già presenti - un database scarsamente protetto, ad esempio - o potrebbe richiedere una raccolta lenta nel tempo mentre scorre, come la raccolta delle transazioni quando arrivano dagli utenti. Mantenere l'accesso per molto tempo richiede la furtività. L'attacco richiede anche un modo per ottenere i dati.

Se l'aggressore cerca semplicemente di fare danni, l'obiettivo è di nuovo quello di accedere a quanti più sistemi e privilegi possibili. Ma c'è un atto di bilanciamento: una volta che il danno inizia, presumibilmente verrà notato, ma più a lungo l'attaccante attende per avviarsi (mentre il malware filtra da sistema a sistema), maggiori sono le possibilità di essere rilevato. Il trasferimento dei dati è meno importante del controllo coordinato del malware. L'idea è di infettare il maggior numero di sistemi possibile, quindi danneggiarli in un punto sincronizzato, prestabilito oa comando.

Le violazioni coinvolgono una serie di elementi. Diamo un'occhiata a ciascuno e vediamo se le VM e le architetture containerizzate possono influenzare la superficie di attacco per ciascuna.