Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/msf/core/exploit/remote/http_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ def configure_http_login_scanner(conf)
evade_uri_fake_params_start: datastore['HTTP::uri_fake_params_start'],
evade_header_folding: datastore['HTTP::header_folding'],
ntlm_domain: datastore['DOMAIN'],
ssl: datastore['SSL'],
digest_auth_iis: datastore['DigestAuthIIS'],
}.merge(conf)
)
Expand Down
58 changes: 28 additions & 30 deletions modules/auxiliary/scanner/http/http_login.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ def initialize
register_options(
[
OptPath.new('USERPASS_FILE', [
false, "File containing users and passwords separated by space, one pair per line",
File.join(Msf::Config.data_directory, "wordlists", "http_default_userpass.txt")
false, 'File containing users and passwords separated by space, one pair per line',
File.join(Msf::Config.data_directory, 'wordlists', 'http_default_userpass.txt')
]),
OptPath.new('USER_FILE', [
false, "File containing users, one per line",
File.join(Msf::Config.data_directory, "wordlists", "http_default_users.txt")
false, 'File containing users, one per line',
File.join(Msf::Config.data_directory, 'wordlists', 'http_default_users.txt')
]),
OptPath.new('PASS_FILE', [
false, "File containing passwords, one per line",
File.join(Msf::Config.data_directory, "wordlists", "http_default_pass.txt")
false, 'File containing passwords, one per line',
File.join(Msf::Config.data_directory, 'wordlists', 'http_default_pass.txt')
]),
OptString.new('AUTH_URI', [ false, "The URI to authenticate against (default:auto)" ]),
OptString.new('REQUESTTYPE', [ false, "Use HTTP-GET or HTTP-PUT for Digest-Auth, PROPFIND for WebDAV (default:GET)", "GET" ])
OptString.new('AUTH_URI', [ false, 'The URI to authenticate against (default:auto)' ]),
OptString.new('REQUESTTYPE', [ false, 'Use HTTP-GET or HTTP-PUT for Digest-Auth, PROPFIND for WebDAV (default:GET)', 'GET' ])
]
)
register_autofilter_ports([ 80, 443, 8080, 8081, 8000, 8008, 8443, 8444, 8880, 8888 ])
Expand All @@ -60,27 +60,25 @@ def initialize
end

def to_uri(uri)
begin
# In case TARGETURI is empty, at least we default to '/'
uri = "/" if uri.blank?
URI(uri)
rescue ::URI::InvalidURIError
raise RuntimeError, "Invalid URI: #{uri}"
end
# In case TARGETURI is empty, at least we default to '/'
uri = '/' if uri.blank?
URI(uri)
rescue ::URI::InvalidURIError
raise "Invalid URI: #{uri}"
end

def find_auth_uri
if datastore['AUTH_URI'].present?
paths = [datastore['AUTH_URI']]
else
paths = %W{
paths = %w[
/
/admin/
/auth/
/manager/
/Management.asp
/ews/
}
]
end

paths.each do |path|
Expand Down Expand Up @@ -114,7 +112,7 @@ def find_auth_uri
'username' => '',
'password' => ''
}, 10)
next if not res
next if !res
end
next unless res.code == 401

Expand All @@ -125,20 +123,20 @@ def find_auth_uri
end

def target_url
proto = "http"
proto = 'http'
if rport == 443 or ssl
proto = "https"
proto = 'https'
end
"#{proto}://#{vhost}:#{rport}#{@uri.to_s}"
"#{proto}://#{vhost}:#{rport}#{@uri}"
end

def run_host(ip)
if (datastore['REQUESTTYPE'] == "PUT") && (datastore['AUTH_URI'].blank?)
print_error("You need need to set AUTH_URI when using PUT Method !")
if (datastore['REQUESTTYPE'] == 'PUT') && (datastore['AUTH_URI'].blank?)
print_error('You need need to set AUTH_URI when using PUT Method !')
return
end

extra_info = ""
extra_info = ''
if rhost != vhost
extra_info = " (#{rhost})"
end
Expand All @@ -149,7 +147,7 @@ def run_host(ip)
return
end

@uri = "/#{@uri}" if @uri[0, 1] != "/"
@uri = "/#{@uri}" if @uri[0, 1] != '/'

print_status("Attempting to login to #{target_url}#{extra_info}")

Expand Down Expand Up @@ -178,33 +176,33 @@ def run_host(ip)

msg = scanner.check_setup
if msg
print_brute :level => :error, :ip => ip, :msg => "Verification failed: #{msg}"
print_brute level: :error, ip: ip, msg: "Verification failed: #{msg}"
return
end

scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: self.fullname,
module_fullname: fullname,
workspace_id: myworkspace_id
)
case result.status
when Metasploit::Model::Login::Status::SUCCESSFUL
print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}'"
print_brute level: :good, ip: ip, msg: "Success: '#{result.credential}'"
credential_data[:private_type] = :password
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
print_brute level: :verror, ip: ip, msg: 'Could not connect'
end
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
print_brute level: :verror, ip: ip, msg: "Failed: '#{result.credential}'"
end
invalidate_login(credential_data)
end
Expand Down
Loading