@@ -27,7 +27,8 @@ def initialize
27
27
'SecureState R&D Team' ,
28
28
'sinn3r' ,
29
29
'Brandon Knight' ,
30
- 'Pete (Bokojan) Arzamendi, #Outlook 2013 updates'
30
+ 'Pete (Bokojan) Arzamendi' , # Outlook 2013 updates
31
+ 'Nate Power' # HTTP timing option
31
32
] ,
32
33
'License' => MSF_LICENSE ,
33
34
'Actions' =>
@@ -81,6 +82,7 @@ def initialize
81
82
OptInt . new ( 'RPORT' , [ true , "The target port" , 443 ] ) ,
82
83
OptAddress . new ( 'RHOST' , [ true , "The target address" , true ] ) ,
83
84
OptBool . new ( 'ENUM_DOMAIN' , [ true , "Automatically enumerate AD domain using NTLM authentication" , true ] ) ,
85
+ OptBool . new ( 'AUTH_TIME' , [ false , "Check HTTP authentication response time" , true ] )
84
86
] , self . class )
85
87
86
88
@@ -163,6 +165,10 @@ def try_user_pass(opts)
163
165
end
164
166
165
167
begin
168
+ if datastore [ 'AUTH_TIME' ]
169
+ start_time = Time . now
170
+ end
171
+
166
172
res = send_request_cgi ( {
167
173
'encode' => true ,
168
174
'uri' => auth_path ,
@@ -171,6 +177,9 @@ def try_user_pass(opts)
171
177
'data' => data
172
178
} )
173
179
180
+ if datastore [ 'AUTH_TIME' ]
181
+ elapsed_time = Time . now - start_time
182
+ end
174
183
rescue ::Rex ::ConnectionError , Errno ::ECONNREFUSED , Errno ::ETIMEDOUT
175
184
print_error ( "#{ msg } HTTP Connection Failed, Aborting" )
176
185
return :abort
@@ -189,7 +198,7 @@ def try_user_pass(opts)
189
198
# Check for a response code to make sure login was valid. Changes from 2010 to 2013.
190
199
# Check if the password needs to be changed.
191
200
if res . headers [ 'location' ] =~ /expiredpassword/
192
- print_good ( "#{ msg } SUCCESSFUL LOGIN. '#{ user } ' : '#{ pass } ': NOTE password change required" )
201
+ print_good ( "#{ msg } SUCCESSFUL LOGIN. #{ elapsed_time } '#{ user } ' : '#{ pass } ': NOTE password change required" )
193
202
report_hash = {
194
203
:host => datastore [ 'RHOST' ] ,
195
204
:port => datastore [ 'RPORT' ] ,
@@ -213,7 +222,7 @@ def try_user_pass(opts)
213
222
headers [ 'Cookie' ] = 'PBack=0;' << res . get_cookies
214
223
else
215
224
# Login didn't work. no point on going on.
216
- vprint_error ( "#{ msg } FAILED LOGIN. '#{ user } ' : '#{ pass } ' (HTTP redirect with reason #{ reason } )" )
225
+ vprint_error ( "#{ msg } FAILED LOGIN. #{ elapsed_time } '#{ user } ' : '#{ pass } ' (HTTP redirect with reason #{ reason } )" )
217
226
return :Skip_pass
218
227
end
219
228
else
@@ -248,12 +257,12 @@ def try_user_pass(opts)
248
257
end
249
258
250
259
if res . redirect?
251
- vprint_error ( "#{ msg } FAILED LOGIN. '#{ user } ' : '#{ pass } ' (response was a #{ res . code } redirect)" )
260
+ vprint_error ( "#{ msg } FAILED LOGIN. #{ elapsed_time } '#{ user } ' : '#{ pass } ' (response was a #{ res . code } redirect)" )
252
261
return :skip_pass
253
262
end
254
263
255
264
if res . body =~ login_check
256
- print_good ( "#{ msg } SUCCESSFUL LOGIN. '#{ user } ' : '#{ pass } '" )
265
+ print_good ( "#{ msg } SUCCESSFUL LOGIN. #{ elapsed_time } '#{ user } ' : '#{ pass } '" )
257
266
258
267
report_hash = {
259
268
:host => datastore [ 'RHOST' ] ,
@@ -267,7 +276,7 @@ def try_user_pass(opts)
267
276
report_auth_info ( report_hash )
268
277
return :next_user
269
278
else
270
- vprint_error ( "#{ msg } FAILED LOGIN. '#{ user } ' : '#{ pass } ' (response body did not match)" )
279
+ vprint_error ( "#{ msg } FAILED LOGIN. #{ elapsed_time } '#{ user } ' : '#{ pass } ' (response body did not match)" )
271
280
return :skip_pass
272
281
end
273
282
end
@@ -318,4 +327,3 @@ def msg
318
327
end
319
328
320
329
end
321
-
0 commit comments