diff --git a/modules/auxiliary/scanner/http/mod_negotiation_brute.rb b/modules/auxiliary/scanner/http/mod_negotiation_brute.rb new file mode 100644 index 0000000000..0104f6d2fd --- /dev/null +++ b/modules/auxiliary/scanner/http/mod_negotiation_brute.rb @@ -0,0 +1,94 @@ +## +# $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/ +## + +## +# mod_negotiation bruter +# http://httpd.apache.org/docs/1.3/content-negotiation.html +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache HTTPD mod_negotiation Filename Bruter', + 'Description' => %q{ + This module performs a brute force attack in order to discover existing files on a + server which uses mod_negotiation. If the filename is found, the IP address and the + files found will be displayed. + }, + 'Author' => [ 'diablohorn [at] gmail.com' ], + 'License' => MSF_LICENSE, + 'Version' => '$Revision$')) + + register_options( + [ + OptString.new('PATH', [ true, "The path to detect mod_negotiation", '/']), + OptString.new('FILEPATH',[true, "path to file with file names", + File.join(Msf::Config.install_root, "data", "wmap", "wmap_files.txt")]) + ], self.class) + end + + def run_host(ip) + ecode = nil + emesg = nil + + tpath = datastore['PATH'] + tfile = datastore['FILEPATH'] + + if tpath[-1,1] != '/' + tpath += '/' + end + + #load the file with filenames into memory + queue = [] + File.open(datastore['FILEPATH'], 'rb').each_line do |fn| + queue << fn.strip + end + + vhost = datastore['VHOST'] || ip + prot = datastore['SSL'] ? 'https' : 'http' + + # + # Send the request and parse the response headers for an alternates header + # + begin + queue.each do |dirname| + reqpath = tpath+dirname + # Send the request the accept header is key here + res = send_request_cgi({ + 'uri' => reqpath, + 'method' => 'GET', + 'ctype' => 'text/html', + 'headers' => {'Accept' => 'a/b'} + }, 20) + + return if not res + + # Check for alternates header and parse them + if(res.code == 406) + chunks = res.headers.to_s.scan(/"(.*?)"/i).flatten + chunks.each do |chunk| + chunk = chunk.to_s + print_status("#{ip} #{tpath}#{chunk}") + end + end + end + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout + rescue ::Timeout::Error, ::Errno::EPIPE + end + + end +end diff --git a/modules/auxiliary/scanner/http/mod_negotiation_scanner.rb b/modules/auxiliary/scanner/http/mod_negotiation_scanner.rb new file mode 100644 index 0000000000..00b91961c6 --- /dev/null +++ b/modules/auxiliary/scanner/http/mod_negotiation_scanner.rb @@ -0,0 +1,75 @@ +## +# $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 Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache HTTPD mod_negotiation scanner', + 'Description' => %q{ + This module scans the webserver of the given host(s) for the existence of mod_negotiate. + If the webserver has mod_negotiation enabled, the IP address will be displayed. + }, + 'Author' => [ 'diablohorn [at] gmail.com' ], + 'License' => MSF_LICENSE, + 'Version' => '$Revision$')) + + register_options( + [ + OptString.new('PATH', [ true, "The path to detect mod_negotiation", '/']), + OptString.new('FILENAME',[true, "Filename to use as a test",'index']) + ], self.class) + end + + def run_host(ip) + ecode = nil + emesg = nil + + tpath = datastore['PATH'] + tfile = datastore['FILENAME'] + + if tpath[-1,1] != '/' + tpath += '/' + end + + vhost = datastore['VHOST'] || ip + prot = datastore['SSL'] ? 'https' : 'http' + + # + # Send the request and parse the response headers for an alternates header + # + begin + # Send the request the accept header is key here + res = send_request_cgi({ + 'uri' => tpath+tfile, + 'method' => 'GET', + 'ctype' => 'text/html', + 'headers' => {'Accept' => 'a/b'} + }, 20) + + return if not res + + # Sheck for alternates header + if(res.code == 406) + print_status("#{ip}") + end + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout + rescue ::Timeout::Error, ::Errno::EPIPE + end + + end +end