Bug 700317 - ghostscript: subroutines within pseudo-operators must themselves be pseudo-operators
Summary: ghostscript: subroutines within pseudo-operators must themselves be pseudo-op...
Status: RESOLVED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: Security (public) (show other bugs)
Version: 9.26
Hardware: PC Linux
: P4 critical
Assignee: Chris Liddell (chrisl)
QA Contact:
URL:
Keywords:
Depends on:
Blocks: 700472
  Show dependency treegraph
 
Reported: 2018-12-04 01:45 UTC by Tavis Ormandy
Modified: 2019-02-08 09:41 UTC (History)
7 users (show)

See Also:
Customer:
Word Size: ---


Attachments
exploit (2.38 KB, application/postscript)
2018-12-04 01:45 UTC, Tavis Ormandy
Details
.bashrc modifying exploit (3.44 KB, application/postscript)
2018-12-04 01:53 UTC, Tavis Ormandy
Details
/typecheck exploit (2.25 KB, application/postscript)
2018-12-12 23:09 UTC, Tavis Ormandy
Details
/typecheck + executeonly exploit (2.57 KB, application/postscript)
2018-12-14 20:32 UTC, Tavis Ormandy
Details
Address force operators exposure (7.10 KB, application/x-compressed-tar)
2019-01-21 12:56 UTC, Chris Liddell (chrisl)
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tavis Ormandy 2018-12-04 01:45:28 UTC
Created attachment 16472 [details]
exploit

I was quickly grepping through the changes in ghostscript 9.26 and noticed that not all the subroutines are pseudo-operators, for example:

http://git.ghostscript.com/?p=ghostpdl.git;a=blob;f=Resource/Init/pdf_draw.ps;h=79733df451c1ecc0a71b08d10e5412ac3e243a9e;hb=gs926#l1123


1123       {
1124         currentglobal pdfdict gcheck .setglobal
1125         pdfdict /.Qqwarning_issued //true .forceput
1126         .setglobal
1127         pdfformaterror
1128       } ifelse

The reason is obvious, it's an ephemeral routine passed to ifelse, but that is irrelevant, you can make ifelse fail via /stackoverflow or /execstackoverflow or whatever.

Actually getting the precise operator to fail is tricky, but I got it to work:

$ ./gs -sDEVICE=ppmraw -dSAFER -f ../../ghostscript-9.26/bin/test.ps 
GPL Ghostscript GIT PRERELEASE 9.27 (2018-11-20)
Copyright (C) 2018 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
(Stage 0: PDFfile)
(Stage 1: q)
(Stage 3: oget)
(Stage 4: pdfemptycount)
(Stage 5: gput)
(Stage 6: resolvestream)
(Stage 7: pdfopdict)
(Stage 8: .pdfruncontext)
(Stage 9: pdfdict)
(Stage 10: /stackoverflow)
(\tLast Parameter:){(\n   **** Error: File has unbalanced q/Q operators \(too many q's\)\n               Output may be incorrect.\n) pdfdict /.Qqwarning_issued --.knownget-- {{--pop--} {--.currentglobal-- pdfdict --scheck-- --.setglobal-- pdfdict /.Qqwarning_issued true --.forceput-- --.setglobal-- pdfformaterror} --ifelse--} {--.currentglobal-- pdfdict --scheck-- --.setglobal-- pdfdict /.Qqwarning_issued true --.forceput-- --.setglobal-- pdfformaterror} --ifelse--}
(\tExtracting .forceput...)
(\tResult:)--.forceput--
(Stage 11: Exploitation...)
(\tShould now have complete control over ghostscript, attempting to read /etc/passwd...)
(root:x:0:0:root:/root:/bin/bash)
(All Done)

Therefore, this is a remote code execution vulnerability. This affects 9.26 and HEAD.

This bug is subject to a 90 day disclosure deadline. After 90 days elapse
or a patch has been made broadly available (whichever is earlier), the bug
report will become visible to the public.
Comment 1 Tavis Ormandy 2018-12-04 01:53:38 UTC
Created attachment 16473 [details]
.bashrc modifying exploit

Here is an example exploit that patches .bashrc just for reference.
Comment 2 Tavis Ormandy 2018-12-11 18:45:51 UTC
Any update on this issue? I'd like to help review the proposed fix if possible, just to think about the consequences. Are you planning to pull the ephemeral routines out and make them pseudo operators?
Comment 3 Chris Liddell (chrisl) 2018-12-12 15:27:04 UTC
(In reply to Tavis Ormandy from comment #2)
> Any update on this issue? I'd like to help review the proposed fix if
> possible, just to think about the consequences. Are you planning to pull the
> ephemeral routines out and make them pseudo operators?

No, giving every single conditional clause a name would be totally impractical.

I've sent a private e-mail with the proposed patch and an explanation.
Comment 4 Tavis Ormandy 2018-12-12 23:09:38 UTC
Created attachment 16550 [details]
/typecheck exploit

Thanks Chris. I reviewed the proposed patch and pointed out that it only works for /stackoverflow, as I mentioned earlier it could be other errors as well.

I sent Chris a full explanation over email, but commenting here just for future reference.

Here is an exploit that uses /typecheck instead, it still works with the proposed patch.

$ ./gs -dSAFER -sDEVICE=ppmraw -sOutputFile=/dev/null -f ghostscript-926-forceput.ps  
GPL Ghostscript GIT PRERELEASE 9.27 (2018-11-20)
Copyright (C) 2018 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
(Stage 0: PDFfile)
(Stage 1: q)
(Stage 3: oget)
(Stage 4: pdfemptycount)
(Stage 5: gput)
(Stage 6: resolvestream)
(Stage 7: pdfopdict)
(Stage 8: .pdfruncontext)
(Stage 9: pdfdict)
Stage 10: /typecheck #1
Stage 10: /typecheck #2
(Stage 11: Exploitation...)
(   Should now have complete control over ghostscript, attempting to read /etc/passwd...)
(root:x:0:0:root:/root:/bin/bash)
Comment 5 Chris Liddell (chrisl) 2018-12-14 07:57:19 UTC
Revised patches sent to Tavis.
Comment 6 Tavis Ormandy 2018-12-14 20:32:42 UTC
Created attachment 16557 [details]
/typecheck + executeonly exploit

I reviewed the new patches, the solution was to mark all ephemeral routines executeonly, like this:

{ foo } executeonly { bar } executeonly ifelse

That won't work because of bug 699816 - just being executeonly doesn't protect the contents unless it's a pseudo-op. I sent Chris a full explanation, and here is an updated exploit that works with executeonly branches.

$ ./gs -dSAFER -sDEVICE=ppmraw -sOutputFile=/dev/null -f ghostscript-926-forceput-typecheck-executeonly-example.ps 
GPL Ghostscript GIT PRERELEASE 9.27 (2018-11-20)
Copyright (C) 2018 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
(Stage 0: PDFfile)
(Stage 1: q)
(Stage 3: oget)
(Stage 4: pdfemptycount)
(Stage 5: gput)
(Stage 6: resolvestream)
(Stage 7: pdfopdict)
(Stage 8: .pdfruncontext)
(Stage 9: pdfdict)
Stage 10: /typecheck #1
Stage 10: /typecheck #2
(Stage 9: pdfdict)
(Stage 9: pdfdict)
Stage 10: /typecheck #3
(Stage 11: Exploitation...)
(   Should now have complete control over ghostscript, attempting to read /etc/passwd...)
(root:x:0:0:root:/root:/bin/bash)
Comment 7 Chris Liddell (chrisl) 2018-12-15 09:43:40 UTC
There was a logic error in an earlier change which exposed the erroring operator in a way I *thought* was no longer possible - I've sent Tavis a patch with a fix for that.
Comment 8 Tavis Ormandy 2019-01-09 20:19:44 UTC
After some discussion I think we have arrived at a comprehensive solution.

Thanks Chris for all the work, this one turned out to be really tough to solve, the complete patchset is really non-trivial.

It will require extra care writing postscript in future, I filed bug 700472 to think about ways to make sure this doesn't accidentally regress.
Comment 9 Tavis Ormandy 2019-01-10 23:12:31 UTC
This is CVE-2019-6116
Comment 10 Chris Liddell (chrisl) 2019-01-21 12:56:02 UTC
Created attachment 16755 [details]
Address force operators exposure
Comment 11 Chris Liddell (chrisl) 2019-01-23 14:28:46 UTC
The fixes for this are now public, thus I'm closing the bug.