How to gain root access to the host filesystem in a Docker environment when you don’t have root or “sudo” privileges on the host? Since many Kubernetes systems still run on Docker and a transition to Podman is ongoing, this article provides a solution to allow access to the host filesystem with root privileges from within a Docker container for making changes or reading files.
In the second part, we will see how to disable this option to lock down the environment from unauthorized access. It is just as dangerous to run processes as root inside a container as it is to run as root on the host, despite the “isolation” of the container. Misconfiguration or exploits can lead to abuse and compromise the supposed isolation.
Access container host filesystem with root privileges:
1. Login to the docker container host. Just assume that you need to access the files which are inside the following directory which is owned by root.
uxpro-$ $ ls -ld /etc drwxr-xr-x 109 root root 4096 Feb 6 17:05 /etc
2. Let’s try to access the directory. Since this directory permission is set to 700, only the root user can access it.
uxpro-$ cd /etc uxpro-$ touch test_file touch: cannot touch 'test_file': Permission denied
3. Start the docker container by mounting “/etc” host filesystem on /mnt in the container.
uxpro-$ docker run -it --rm -u root -v /etc:/mnt nginx:latest bash Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx 01b5b2efb836: Pull complete db354f722736: Pull complete abb02e674be5: Pull complete 214be53c3027: Pull complete a69afcef752d: Pull complete 625184acb94e: Pull complete Digest: sha256:c54fb26749e49dc2df77c6155e8b5f0f78b781b7f0eadd96ecfabdcdfa5b1ec4 Status: Downloaded newer image for nginx:latest root@3f7c7cee564d:/# cd /mnt root@3f7c7cee564d:/mnt# ls -lrt total 916 -rw-r--r-- 1 root root 887 Apr 1 2013 rpc -rw-r--r-- 1 root root 2932 Apr 1 2013 protocols -rw-r--r-- 1 root root 280 Jun 20 2014 fuse.conf -rw-r--r-- 1 root root 3663 Jun 20 2016 screenrc -rw-r--r-- 1 root root 604 Sep 15 2018 deluser.conf
4. Create a “test_file” under “/mnt” – which is actually host’s /etc/ filesystem.
root@feae8285eb31:/# cd /mnt root@feae8285eb31:/mnt# touch test_file root@feae8285eb31:/mnt# ls -lrt test_file -rw-r--r-- 1 root root 0 Feb 6 17:16 test_file root@feae8285eb31:/mnt# exit exit uxpro $ ls -lrt /etc/test_file -rw-r--r-- 1 root root 0 Feb 6 17:16 /etc/test_file uxpro $
As long as you only practice this hack in a controlled environment such as a lab or local system, everything will be fine. However, it is not advisable to have systems in production with such a significant security vulnerability. In the next section of the article, we will provide steps to mitigate this security risk by disabling it.
How to prevent user from privilege-escalation on docker host ?
On the docker host, identify user and group which can be used by the docker containers. If you do not have one , create it like below.
1. Create a new user called “dockerusr”
uxpro $ sudo adduser --system --no-create-home --disabled-password --d isabled-login --gecos '' dockerusr Adding system user `dockerusr' (UID 115) ... Adding new user `dockerusr' (UID 115) with group `nogroup' ... Not creating home directory `/home/dockerusr'.
2. Create a new group called “dockergrp”
uxpro $ sudo addgroup --system dockergrp Adding group `dockergrp' (GID 124) ... Done.
3. Add the newly created user to the group.
uxpro $ sudo adduser dockerusr dockergrp Adding user `dockerusr' to group `dockergrp' ... Adding user dockerusr to group dockergrp Done.
Add the user to docker group.
uxpro $ sudo adduser dockerusr docker Adding user `dockerusr' to group `docker' ... Adding user dockerusr to group docker Done.
4. Update the “subuid” file with newly created user.
uxpro $ echo "dockerusr:200000:65536" >> /etc/subuid uxpro $ cat /etc/subuid vagrant:100000:65536 lingesh:165536:65536 dockerusr:200000:65536
5. Updae the “subgid” file with newly created group.
uxpro $ echo "dockergrp:200000:65536" >> /etc/subgid uxpro $ cat /etc/subgid vagrant:100000:65536 lingesh:165536:65536 dockergrp:200000:65536
6. If “/etc/docker” directory is not exists, create a new directory and then create a file called “daemon.json”.
uxpro $ mkdir -p /etc/docker uxpro $ vi /etc/docker/daemon.json uxpro $ cat /etc/docker/daemon.json { "userns-remap": "dockerusr:dockergrp" } uxpro $
7. Restart the docker daemon.
uxpro $ systemctl restart docker uxpro $ systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2023-02-07 15:51:19 UTC; 1min 0s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 77936 (dockerd) Tasks: 7 Memory: 27.8M CGroup: /system.slice/docker.service └─77936 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
8. Let’s try to start the container by mounting host’s “/etc” on container’s “/mnt”.
$ docker run -it --rm -u root -v /etc:/mnt nginx:latest bash Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx 01b5b2efb836: Pull complete db354f722736: Pull complete abb02e674be5: Pull complete 214be53c3027: Pull complete a69afcef752d: Pull complete 625184acb94e: Pull complete Digest: sha256:c54fb26749e49dc2df77c6155e8b5f0f78b781b7f0eadd96ecfabdcdfa5b1ec4 Status: Downloaded newer image for nginx:latest root@728b0b25ec5a:/#
9. Let’s verify the “/mnt” content. (host’s “/etc/” filesystem).
root@728b0b25ec5a:/# cd /mnt root@728b0b25ec5a:/mnt# ls -lrt total 920 -rw-r--r-- 1 nobody nogroup 887 Apr 1 2013 rpc -rw-r--r-- 1 nobody nogroup 2932 Apr 1 2013 protocols -rw-r--r-- 1 nobody nogroup 280 Jun 20 2014 fuse.conf -rw-r--r-- 1 nobody nogroup 3663 Jun 20 2016 screenrc -rw-r--r-- 1 nobody nogroup 604 Sep 15 2018 deluser.conf -rw-r----- 1 nobody nogroup 144 Nov 12 2018 at.deny -rw-r--r-- 1 nobody nogroup 1260 Dec 14 2018 ucf.conf -rw-r--r-- 1 nobody nogroup 533 Jan 21 2019 logrotate.conf -rw-r--r-- 1 nobody nogroup 14867 Feb 1 2019 ltrace.conf
Let’s try to create a empty on “/mnt” now.
root@728b0b25ec5a:/mnt# touch 3 touch: cannot touch '3': Permission denied
We have successfully blocked the root access on the mounts. “userns-remap” is a feature in Docker that allows for user namespace remapping. It provides a way to map the host’s user ID (UID) and group ID (GID) to a different range of IDs inside a container, effectively separating the host’s user and group IDs from the container’s IDs. This helps in situations where the UID and GID inside a container should not match those on the host system, such as in cases where the container runs as a privileged user or where the host and container IDs conflict.
Hope this article is informative to you.
Leave a Reply