Metasploit Module: Docker cgroups Container Escape
Type: exploit
Path: modules/exploits/linux/local/docker_cgroup_escape.rb
Disclosure date: 2022-02-04
References: URL-https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=24f[PII_REDACTED]aa120d07c03d9289519c2fe02af, URL-https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/, URL-https://github.com/T1erno/CVE-2022-0492-Docker-Breakout-Checker-and-PoC, URL-https://github.com/PaloAltoNetworks/can-ctr-escape-cve-2022-0492, URL-https://github.com/SofianeHamlaoui/CVE-2022-0492-Checker/blob/main/escape-check.sh, URL-https://pwning.systems/posts/escaping-containers-for-fun/, URL-https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html, URL-https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation, URL-https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/, CVE-2022-0492
Targets: BINARY, CMD

Description:
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.

Check method (fingerprinting):
print_status('Unable to determine host OS, this check method is unlikely to be accurate if the host isn\'t Ubuntu')
    release = kernel_release
    # https://people.canonical.com/~ubuntu-security/cve/2022/CVE-2022-0492
    begin
      release_short = Rex::Version.new(release.split('-').first)
      release_long = Rex::Version.new(release.split('-')[0..1].join('-'))
      if release_short >= Rex::Version.new('5.13.0') && release_long < Rex::Version.new('5.13.0-37.42') || # Ubuntu 21.10
         release_short >= Rex::Version.new('5.4.0') && release_long < Rex::Version.new('5.4.0-105.119') || # Ubuntu 20.04 LTS
         release_short >= Rex::Version.new('4.15.0') && release_long < Rex::Version.new('4.15.0-173.182') || # Ubuntu 18.04 LTS
         release_short >= Rex::Version.new('4.4.0') && release_long < Rex::Version.new('4.4.0-222.255') # Ubuntu 16.04 ESM
        return CheckCode::Vulnerable("IF host OS is Ubuntu, kernel version #{release} is vulnerable")
      end
    rescue ArgumentError => e
      return CheckCode::Safe("Error determining or processing kernel release (#{release}) into known format: #{e}")
    end

    CheckCode::Safe("Kernel version #{release} may not be vulnerable depending on the host OS")
  end