Sicurezza di Docker
Reading time: 18 minutes
tip
Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos di github.
Sicurezza di Base del Motore Docker
Il motore Docker utilizza i Namespaces e i Cgroups del kernel Linux per isolare i container, offrendo un livello base di sicurezza. Ulteriore protezione è fornita tramite il Capabilities dropping, Seccomp e SELinux/AppArmor, migliorando l'isolamento dei container. Un auth plugin può ulteriormente limitare le azioni degli utenti.
Accesso Sicuro al Motore Docker
Il motore Docker può essere accessibile localmente tramite un socket Unix o remotamente utilizzando HTTP. Per l'accesso remoto, è essenziale utilizzare HTTPS e TLS per garantire riservatezza, integrità e autenticazione.
Il motore Docker, per impostazione predefinita, ascolta sul socket Unix a unix:///var/run/docker.sock
. Nei sistemi Ubuntu, le opzioni di avvio di Docker sono definite in /etc/default/docker
. Per abilitare l'accesso remoto all'API e al client Docker, esporre il demone Docker su un socket HTTP aggiungendo le seguenti impostazioni:
DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H tcp://192.168.56.101:2376"
sudo service docker restart
Tuttavia, esporre il daemon Docker su HTTP non è raccomandato a causa di preoccupazioni di sicurezza. È consigliabile proteggere le connessioni utilizzando HTTPS. Ci sono due approcci principali per garantire la connessione:
- Il client verifica l'identità del server.
- Sia il client che il server si autenticano reciprocamente.
I certificati vengono utilizzati per confermare l'identità di un server. Per esempi dettagliati di entrambi i metodi, fare riferimento a questa guida.
Sicurezza delle Immagini dei Container
Le immagini dei container possono essere memorizzate in repository privati o pubblici. Docker offre diverse opzioni di archiviazione per le immagini dei container:
- Docker Hub: Un servizio di registry pubblico di Docker.
- Docker Registry: Un progetto open-source che consente agli utenti di ospitare il proprio registry.
- Docker Trusted Registry: L'offerta commerciale di registry di Docker, con autenticazione utente basata su ruoli e integrazione con i servizi di directory LDAP.
Scansione delle Immagini
I container possono avere vulnerabilità di sicurezza sia a causa dell'immagine di base che a causa del software installato sopra l'immagine di base. Docker sta lavorando a un progetto chiamato Nautilus che esegue la scansione di sicurezza dei container e elenca le vulnerabilità. Nautilus funziona confrontando ogni layer dell'immagine del container con il repository delle vulnerabilità per identificare le falle di sicurezza.
Per ulteriori informazioni leggi questo.
docker scan
Il comando docker scan
consente di eseguire la scansione delle immagini Docker esistenti utilizzando il nome o l'ID dell'immagine. Ad esempio, eseguire il seguente comando per scansionare l'immagine hello-world:
docker scan hello-world
Testing hello-world...
Organization: docker-desktop-test
Package manager: linux
Project name: docker-image|hello-world
Docker image: hello-world
Licenses: enabled
✓ Tested 0 dependencies for known issues, no vulnerable paths found.
Note that we do not currently have vulnerability data for your image.
trivy -q -f json <container_name>:<tag>
snyk container test <image> --json-file-output=<output file> --severity-threshold=high
clair-scanner -w example-alpine.yaml --ip YOUR_LOCAL_IP alpine:3.5
Firma dell'immagine Docker
La firma dell'immagine Docker garantisce la sicurezza e l'integrità delle immagini utilizzate nei container. Ecco una spiegazione condensata:
- Docker Content Trust utilizza il progetto Notary, basato su The Update Framework (TUF), per gestire la firma delle immagini. Per ulteriori informazioni, vedere Notary e TUF.
- Per attivare la fiducia nei contenuti Docker, impostare
export DOCKER_CONTENT_TRUST=1
. Questa funzione è disattivata per impostazione predefinita nelle versioni di Docker 1.10 e successive. - Con questa funzione attivata, possono essere scaricate solo immagini firmate. Il primo push dell'immagine richiede l'impostazione di frasi segrete per le chiavi root e di tagging, con Docker che supporta anche Yubikey per una maggiore sicurezza. Maggiori dettagli possono essere trovati qui.
- Tentare di scaricare un'immagine non firmata con la fiducia nei contenuti attivata risulta in un errore "No trust data for latest".
- Per i push delle immagini dopo il primo, Docker richiede la frase segreta della chiave del repository per firmare l'immagine.
Per eseguire il backup delle tue chiavi private, usa il comando:
tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private
Quando si cambia host Docker, è necessario spostare le chiavi root e repository per mantenere le operazioni.
Funzionalità di Sicurezza dei Container
Riepilogo delle Funzionalità di Sicurezza dei Container
Principali Funzionalità di Isolamento dei Processi
Negli ambienti containerizzati, isolare i progetti e i loro processi è fondamentale per la sicurezza e la gestione delle risorse. Ecco una spiegazione semplificata dei concetti chiave:
Namespace
- Scopo: Garantire l'isolamento delle risorse come processi, rete e filesystem. In particolare in Docker, gli namespace mantengono i processi di un container separati dall'host e da altri container.
- Utilizzo di
unshare
: Il comandounshare
(o la syscall sottostante) è utilizzato per creare nuovi namespace, fornendo un ulteriore livello di isolamento. Tuttavia, mentre Kubernetes non blocca intrinsecamente questo, Docker lo fa. - Limitazione: Creare nuovi namespace non consente a un processo di tornare ai namespace predefiniti dell'host. Per penetrare nei namespace dell'host, in genere è necessario avere accesso alla directory
/proc
dell'host, utilizzandonsenter
per l'ingresso.
Gruppi di Controllo (CGroups)
- Funzione: Utilizzati principalmente per allocare risorse tra i processi.
- Aspetto di Sicurezza: I CGroups stessi non offrono sicurezza di isolamento, tranne per la funzionalità
release_agent
, che, se configurata in modo errato, potrebbe essere sfruttata per accesso non autorizzato.
Riduzione delle Capacità
- Importanza: È una funzionalità di sicurezza cruciale per l'isolamento dei processi.
- Funzionalità: Limita le azioni che un processo root può eseguire riducendo certe capacità. Anche se un processo viene eseguito con privilegi di root, la mancanza delle capacità necessarie impedisce l'esecuzione di azioni privilegiate, poiché le syscall falliranno a causa di permessi insufficienti.
Queste sono le capacità rimanenti dopo che il processo ha ridotto le altre:
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Seccomp
È abilitato per impostazione predefinita in Docker. Aiuta a limitare ulteriormente le syscalls che il processo può chiamare.
Il profilo Seccomp predefinito di Docker può essere trovato in https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
AppArmor
Docker ha un modello che puoi attivare: https://github.com/moby/moby/tree/master/profiles/apparmor
Questo permetterà di ridurre le capacità, le syscalls, l'accesso a file e cartelle...
Namespaces
I Namespaces sono una funzionalità del kernel Linux che partiziona le risorse del kernel in modo tale che un insieme di processi veda un insieme di risorse mentre un altro insieme di processi vede un insieme diverso di risorse. La funzionalità funziona avendo lo stesso namespace per un insieme di risorse e processi, ma quei namespace si riferiscono a risorse distinte. Le risorse possono esistere in più spazi.
Docker utilizza i seguenti Namespaces del kernel Linux per ottenere l'isolamento dei Container:
- pid namespace
- mount namespace
- network namespace
- ipc namespace
- UTS namespace
Per maggiori informazioni sui namespaces controlla la seguente pagina:
{{#ref}} namespaces/ {{#endref}}
cgroups
La funzionalità del kernel Linux cgroups fornisce la capacità di ristretto risorse come cpu, memoria, io, larghezza di banda di rete tra un insieme di processi. Docker consente di creare Container utilizzando la funzionalità cgroup che consente il controllo delle risorse per il Container specifico.
Di seguito è riportato un Container creato con la memoria dello spazio utente limitata a 500m, la memoria del kernel limitata a 50m, la condivisione della cpu a 512, il blkioweight a 400. La condivisione della CPU è un rapporto che controlla l'uso della CPU del Container. Ha un valore predefinito di 1024 e un intervallo tra 0 e 1024. Se tre Container hanno la stessa condivisione della CPU di 1024, ciascun Container può utilizzare fino al 33% della CPU in caso di contesa delle risorse CPU. Il blkio-weight è un rapporto che controlla l'IO del Container. Ha un valore predefinito di 500 e un intervallo tra 10 e 1000.
docker run -it -m 500M --kernel-memory 50M --cpu-shares 512 --blkio-weight 400 --name ubuntu1 ubuntu bash
Per ottenere il cgroup di un container puoi fare:
docker run -dt --rm denial sleep 1234 #Run a large sleep inside a Debian container
ps -ef | grep 1234 #Get info about the sleep process
ls -l /proc/<PID>/ns #Get the Group and the namespaces (some may be uniq to the hosts and some may be shred with it)
Per ulteriori informazioni controlla:
{{#ref}} cgroups.md {{#endref}}
Capacità
Le capacità consentono un controllo più fine delle capacità che possono essere consentite per l'utente root. Docker utilizza la funzionalità di capacità del kernel Linux per limitare le operazioni che possono essere eseguite all'interno di un Container indipendentemente dal tipo di utente.
Quando un container docker viene eseguito, il processo abbandona capacità sensibili che il processo potrebbe utilizzare per sfuggire all'isolamento. Questo cerca di garantire che il processo non sarà in grado di eseguire azioni sensibili e fuggire:
{{#ref}} ../linux-capabilities.md {{#endref}}
Seccomp in Docker
Questa è una funzionalità di sicurezza che consente a Docker di limitare le syscalls che possono essere utilizzate all'interno del container:
{{#ref}} seccomp.md {{#endref}}
AppArmor in Docker
AppArmor è un miglioramento del kernel per confinare i container a un insieme limitato di risorse con profili per programma.:
{{#ref}} apparmor.md {{#endref}}
SELinux in Docker
- Sistema di Etichettatura: SELinux assegna un'etichetta unica a ogni processo e oggetto del filesystem.
- Applicazione delle Politiche: Applica politiche di sicurezza che definiscono quali azioni un'etichetta di processo può eseguire su altre etichette all'interno del sistema.
- Etichette dei Processi del Container: Quando i motori dei container avviano processi del container, di solito viene assegnata un'etichetta SELinux confinata, comunemente
container_t
. - Etichettatura dei File all'interno dei Container: I file all'interno del container sono solitamente etichettati come
container_file_t
. - Regole di Politica: La politica SELinux garantisce principalmente che i processi con l'etichetta
container_t
possano interagire solo (leggere, scrivere, eseguire) con file etichettati comecontainer_file_t
.
Questo meccanismo garantisce che anche se un processo all'interno di un container viene compromesso, è confinato a interagire solo con oggetti che hanno le etichette corrispondenti, limitando significativamente il potenziale danno derivante da tali compromessi.
{{#ref}} ../selinux.md {{#endref}}
AuthZ & AuthN
In Docker, un plugin di autorizzazione gioca un ruolo cruciale nella sicurezza decidendo se consentire o bloccare le richieste al demone Docker. Questa decisione viene presa esaminando due contesti chiave:
- Contesto di Autenticazione: Questo include informazioni complete sull'utente, come chi sono e come si sono autenticati.
- Contesto del Comando: Questo comprende tutti i dati pertinenti relativi alla richiesta effettuata.
Questi contesti aiutano a garantire che solo le richieste legittime da parte di utenti autenticati vengano elaborate, migliorando la sicurezza delle operazioni Docker.
{{#ref}} authz-and-authn-docker-access-authorization-plugin.md {{#endref}}
DoS da un container
Se non limiti correttamente le risorse che un container può utilizzare, un container compromesso potrebbe causare un DoS all'host su cui è in esecuzione.
- CPU DoS
# stress-ng
sudo apt-get install -y stress-ng && stress-ng --vm 1 --vm-bytes 1G --verify -t 5m
# While loop
docker run -d --name malicious-container -c 512 busybox sh -c 'while true; do :; done'
- Bandwidth DoS
nc -lvp 4444 >/dev/null & while true; do cat /dev/urandom | nc <target IP> 4444; done
Flag Docker Interessanti
--privileged flag
Nella pagina seguente puoi imparare cosa implica il flag --privileged
:
{{#ref}} docker-privileged.md {{#endref}}
--security-opt
no-new-privileges
Se stai eseguendo un container in cui un attaccante riesce ad accedere come utente a bassa privilegio. Se hai un binary suid mal configurato, l'attaccante potrebbe abusarne e escalare i privilegi all'interno del container. Questo potrebbe permettergli di fuggire da esso.
Eseguire il container con l'opzione no-new-privileges
abilitata prevenirà questo tipo di escalation dei privilegi.
docker run -it --security-opt=no-new-privileges:true nonewpriv
Altro
#You can manually add/drop capabilities with
--cap-add
--cap-drop
# You can manually disable seccomp in docker with
--security-opt seccomp=unconfined
# You can manually disable seccomp in docker with
--security-opt apparmor=unconfined
# You can manually disable selinux in docker with
--security-opt label:disable
Per ulteriori opzioni --security-opt
controlla: https://docs.docker.com/engine/reference/run/#security-configuration
Altre Considerazioni sulla Sicurezza
Gestione dei Segreti: Migliori Pratiche
È fondamentale evitare di incorporare segreti direttamente nelle immagini Docker o di utilizzare variabili d'ambiente, poiché questi metodi espongono le tue informazioni sensibili a chiunque abbia accesso al container tramite comandi come docker inspect
o exec
.
I volumi Docker sono un'alternativa più sicura, raccomandata per accedere a informazioni sensibili. Possono essere utilizzati come un filesystem temporaneo in memoria, mitigando i rischi associati a docker inspect
e al logging. Tuttavia, gli utenti root e quelli con accesso exec
al container potrebbero comunque accedere ai segreti.
I segreti Docker offrono un metodo ancora più sicuro per gestire informazioni sensibili. Per le istanze che richiedono segreti durante la fase di build dell'immagine, BuildKit presenta una soluzione efficiente con supporto per segreti a tempo di build, migliorando la velocità di build e fornendo funzionalità aggiuntive.
Per sfruttare BuildKit, può essere attivato in tre modi:
- Tramite una variabile d'ambiente:
export DOCKER_BUILDKIT=1
- Prefissando i comandi:
DOCKER_BUILDKIT=1 docker build .
- Abilitandolo per impostazione predefinita nella configurazione di Docker:
{ "features": { "buildkit": true } }
, seguito da un riavvio di Docker.
BuildKit consente l'uso di segreti a tempo di build con l'opzione --secret
, assicurando che questi segreti non siano inclusi nella cache di build dell'immagine o nell'immagine finale, utilizzando un comando come:
docker build --secret my_key=my_value ,src=path/to/my_secret_file .
Per i segreti necessari in un container in esecuzione, Docker Compose e Kubernetes offrono soluzioni robuste. Docker Compose utilizza una chiave secrets
nella definizione del servizio per specificare i file segreti, come mostrato in un esempio di docker-compose.yml
:
version: "3.7"
services:
my_service:
image: centos:7
entrypoint: "cat /run/secrets/my_secret"
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret_file.txt
Questa configurazione consente l'uso di segreti durante l'avvio dei servizi con Docker Compose.
Negli ambienti Kubernetes, i segreti sono supportati nativamente e possono essere ulteriormente gestiti con strumenti come Helm-Secrets. I controlli di accesso basati sui ruoli (RBAC) di Kubernetes migliorano la sicurezza nella gestione dei segreti, simile a Docker Enterprise.
gVisor
gVisor è un kernel applicativo, scritto in Go, che implementa una parte sostanziale della superficie di sistema Linux. Include un runtime Open Container Initiative (OCI) chiamato runsc
che fornisce un confine di isolamento tra l'applicazione e il kernel host. Il runtime runsc
si integra con Docker e Kubernetes, rendendo semplice l'esecuzione di container sandboxed.
{{#ref}} https://github.com/google/gvisor {{#endref}}
Kata Containers
Kata Containers è una comunità open source che lavora per costruire un runtime di container sicuro con macchine virtuali leggere che si comportano e performano come container, ma forniscono un isolamento del carico di lavoro più forte utilizzando la tecnologia di virtualizzazione hardware come secondo strato di difesa.
{{#ref}} https://katacontainers.io/ {{#endref}}
Suggerimenti Riassuntivi
- Non utilizzare il flag
--privileged
o montare un socket Docker all'interno del container. Lo socket docker consente di avviare container, quindi è un modo semplice per prendere il controllo completo dell'host, ad esempio, eseguendo un altro container con il flag--privileged
. - Non eseguire come root all'interno del container. Utilizza un utente diverso e namespace utente. Il root nel container è lo stesso dell'host a meno che non venga rimappato con gli namespace utente. È solo leggermente limitato da, principalmente, namespace Linux, capacità e cgroups.
- Elimina tutte le capacità (
--cap-drop=all
) e abilita solo quelle necessarie (--cap-add=...
). Molti carichi di lavoro non necessitano di capacità e aggiungerle aumenta l'ambito di un potenziale attacco. - Utilizza l'opzione di sicurezza “no-new-privileges” per impedire ai processi di acquisire più privilegi, ad esempio tramite binari suid.
- Limita le risorse disponibili per il container. I limiti delle risorse possono proteggere la macchina da attacchi di denial of service.
- Regola i profili seccomp, AppArmor (o SELinux) per limitare le azioni e le syscalls disponibili per il container al minimo necessario.
- Utilizza immagini docker ufficiali e richiedi firme o costruisci le tue basate su di esse. Non ereditare o utilizzare immagini backdoored. Inoltre, conserva le chiavi root e le frasi di accesso in un luogo sicuro. Docker ha piani per gestire le chiavi con UCP.
- Ricostruisci regolarmente le tue immagini per applicare patch di sicurezza all'host e alle immagini.
- Gestisci i tuoi segreti con saggezza in modo che sia difficile per l'attaccante accedervi.
- Se esponi il demone docker utilizza HTTPS con autenticazione client e server.
- Nel tuo Dockerfile, preferisci COPY invece di ADD. ADD estrae automaticamente i file compressi e può copiare file da URL. COPY non ha queste capacità. Ogni volta che è possibile, evita di utilizzare ADD per non essere suscettibile ad attacchi tramite URL remoti e file Zip.
- Avere container separati per ogni micro-servizio
- Non mettere ssh all'interno del container, “docker exec” può essere utilizzato per ssh nel Container.
- Avere immagini di container più piccole
Docker Breakout / Privilege Escalation
Se sei all'interno di un container docker o hai accesso a un utente nel gruppo docker, potresti provare a fuggire e aumentare i privilegi:
{{#ref}} docker-breakout-privilege-escalation/ {{#endref}}
Bypass del Plugin di Autenticazione Docker
Se hai accesso allo socket docker o hai accesso a un utente nel gruppo docker ma le tue azioni sono limitate da un plugin di autenticazione docker, verifica se puoi bypassarlo:
{{#ref}} authz-and-authn-docker-access-authorization-plugin.md {{#endref}}
Hardening Docker
- Lo strumento docker-bench-security è uno script che controlla dozzine di best practices comuni per il deployment di container Docker in produzione. I test sono tutti automatizzati e si basano sul CIS Docker Benchmark v1.3.1.
Devi eseguire lo strumento dall'host che esegue docker o da un container con privilegi sufficienti. Scopri come eseguirlo nel README: https://github.com/docker/docker-bench-security.
Riferimenti
- https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/
- https://twitter.com/_fel1x/status/1151487051986087936
- https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-1overview/
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-3engine-access/
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-4container-image/
- https://en.wikipedia.org/wiki/Linux_namespaces
- https://towardsdatascience.com/top-20-docker-security-tips-81c41dd06f57
- https://www.redhat.com/sysadmin/privileged-flag-container-engines
- https://docs.docker.com/engine/extend/plugins_authorization
- https://towardsdatascience.com/top-20-docker-security-tips-81c41dd06f57
- https://resources.experfy.com/bigdata-cloud/top-20-docker-security-tips/
tip
Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos di github.