diff --git a/modules/auxiliary/scanner/http/wmap_web_vulndb.rb b/modules/auxiliary/scanner/http/wmap_web_vulndb.rb new file mode 100644 index 0000000000..b89ea0b761 --- /dev/null +++ b/modules/auxiliary/scanner/http/wmap_web_vulndb.rb @@ -0,0 +1,184 @@ +## +# 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 'rex/proto/http' +require 'msf/core' + + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::WMAPScanServer + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'HTTP Favicon Scanner', + 'Description' => %q{ + This module identifies the type of webserver based on the favicon. + }, + 'Author' => [ 'et' ], + 'License' => BSD_LICENSE, + 'Version' => '$Revision: 7629 $')) + + register_options( + [ + OptString.new('PATH', [ true, "Original test path", '/']), + OptPath.new('VULNCSV', [ false, "Path of vulnerabilities csv file to use", + File.join(Msf::Config.install_root, "data", "wmap", "wmap_vulns.csv") + ] + ) + ], self.class) + + register_advanced_options( + [ + OptInt.new('ErrorCode', [ true, "The expected http code for non existant files", 404]), + OptPath.new('HTTP404Sigs', [ false, "Path of 404 signatures to use", + File.join(Msf::Config.install_root, "data", "wmap", "wmap_404s.txt") + ] + ), + OptBool.new('NoDetailMessages', [ false, "Do not display detailed test messages", true ]), + OptBool.new('ForceCode', [ false, "Force detection using HTTP code", false ]), + OptInt.new('TestThreads', [ true, "Number of test threads", 25]) + ], self.class) + + end + + def run_host(ip) + conn = false + usecode = datastore['ForceCode'] + + tpath = datastore['PATH'] + if tpath[-1,1] != '/' + tpath += '/' + end + + nt = datastore['TestThreads'].to_i + nt = 1 if nt == 0 + + dm = datastore['NoDetailMessages'] + + queue = [] + + File.open(datastore['VULNCSV']).each do |testf| + queue << testf.strip + end + + # + # Detect error code + # + ecode = datastore['ErrorCode'].to_i + begin + randfile = Rex::Text.rand_text_alpha(5).chomp + + res = send_request_cgi({ + 'uri' => tpath+randfile, + 'method' => 'GET', + 'ctype' => 'text/html' + }, 20) + + return if not res + + tcode = res.code.to_i + + # Look for a string we can signature on as well + if(tcode >= 200 and tcode <= 299) + File.open(datastore['HTTP404Sigs']).each do |str| + if(res.body.index(str)) + emesg = str + break + end + end + + if(not emesg) + print_status("Using first 256 bytes of the response as 404 string") + emesg = res.body[0,256] + else + print_status("Using custom 404 string of '#{emesg}'") + end + else + ecode = tcode + print_status("Using code '#{ecode}' as not found.") + end + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout + conn = false + rescue ::Timeout::Error, ::Errno::EPIPE + end + + + while(not queue.empty?) + t = [] + 1.upto(nt) do + t << Thread.new(queue.shift) do |testf| + Thread.current.kill if not testf + + testarr = [] + testfvuln = "" + testmesg = "" + testnote = "" + foundstr = false + + testarr = testf.split(',') + + testfvuln = testarr[0].to_s + testmesg = testarr[1].to_s + testnote = testarr[2].to_s + + res = send_request_cgi({ + 'uri' => tpath+testfvuln, + 'method' => 'GET', + 'ctype' => 'text/plain' + }, 20) + + + if testmesg.empty? or usecode + if(not res or ((res.code.to_i == ecode) or (emesg and res.body.index(emesg)))) + if dm == false + print_status("NOT Found #{wmap_base_url}#{tpath}#{testfvuln} #{res.code.to_i}") + #blah + end + else + if res.code.to_i == 400 and ecode != 400 + print_error("Server returned an error code. #{wmap_base_url}#{tpath}#{testfvuln} #{res.code.to_i}") + else + print_status("FOUND #{wmap_base_url}#{tpath}#{testfvuln} [#{res.code.to_i}] #{testnote}") + + report_note( + :host => ip, + :proto => 'HTTP', + :port => rport, + :type => 'FILE', + :data => "#{tpath}#{testfvuln} Code: #{res.code}" + ) + end + end + else + if res and res.body.include?(testmesg) + print_status("FOUND #{wmap_base_url}#{tpath}#{testfvuln} [#{res.code.to_i}] #{testnote}") + + report_note( + :host => ip, + :proto => 'HTTP', + :port => rport, + :type => 'FILE', + :data => "#{tpath}#{testfvuln} Code: #{res.code}" + ) + else + if dm == false + print_status("NOT Found #{wmap_base_url}#{tpath}#{testfvuln} #{res.code.to_i}") + #blah + end + end + end + end + end + t.map{|x| x.join } + end + end +end