Bug 699671

Summary: handling /undefined results in SEGV
Product: Ghostscript Reporter: Tavis Ormandy <taviso>
Component: Security (public)Assignee: Chris Liddell (chrisl) <chris.liddell>
Status: RESOLVED FIXED    
Severity: critical CC: cbuissar, scorneli
Priority: P1    
Version: unspecified   
Hardware: PC   
OS: Linux   
Customer: Word Size: ---

Description Tavis Ormandy 2018-08-24 20:55:10 UTC
This was found by fuzzing, I don't know what's causing the crash:

$ gdb ./gs
(gdb) r -dSAFER -sDEVICE=ppmraw 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
GPL Ghostscript GIT PRERELEASE 9.24 (2018-03-21)
Copyright (C) 2018 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
GS>errordict /undefined {} put
GS>{ runpdfbegin } stopped {} if
GS>undefined % any undefined name will do
GS<1>CS

Program received signal SIGSEGV, Segmentation fault.
0x000055555721cd1a in ?? ()
(gdb) bt
#0  0x000055555721cd1a in ?? ()
#1  0x0000555555c7f318 in interp (pi_ctx_p=0x55555701b080, pref=0x7fffffffd890, perror_object=0x7fffffffdaa0) at ./psi/interp.c:1212
#2  0x0000555555c7da43 in gs_call_interp (pi_ctx_p=0x55555701b080, pref=0x7fffffffd9d0, user_errors=1, pexit_code=0x7fffffffdab8, perror_object=0x7fffffffdaa0) at ./psi/interp.c:517
#3  0x0000555555c7d877 in gs_interpret (pi_ctx_p=0x55555701b080, pref=0x7fffffffd9d0, user_errors=1, pexit_code=0x7fffffffdab8, perror_object=0x7fffffffdaa0) at ./psi/interp.c:474
#4  0x0000555555c7062b in gs_main_interpret (minst=0x55555701afe0, pref=0x7fffffffd9d0, user_errors=1, pexit_code=0x7fffffffdab8, perror_object=0x7fffffffdaa0) at ./psi/imain.c:235
#5  0x0000555555c71615 in gs_main_run_string_end (minst=0x55555701afe0, user_errors=1, pexit_code=0x7fffffffdab8, perror_object=0x7fffffffdaa0) at ./psi/imain.c:651
#6  0x0000555555c714df in gs_main_run_string_with_length (minst=0x55555701afe0, str=0x555555e02729 "systemdict /start get exec", length=26, user_errors=1, pexit_code=0x7fffffffdab8, perror_object=0x7fffffffdaa0) at ./psi/imain.c:609
#7  0x0000555555c71451 in gs_main_run_string (minst=0x55555701afe0, str=0x555555e02729 "systemdict /start get exec", user_errors=1, pexit_code=0x7fffffffdab8, perror_object=0x7fffffffdaa0) at ./psi/imain.c:591
#8  0x0000555555c74fe8 in run_string (minst=0x55555701afe0, str=0x555555e02729 "systemdict /start get exec", options=2) at ./psi/imainarg.c:1033
#9  0x0000555555c73053 in gs_main_run_start (minst=0x55555701afe0) at ./psi/imainarg.c:304
#10 0x000055555566ef0d in main (argc=3, argv=0x7fffffffdc08) at ./psi/gs.c:125
Comment 1 Ray Johnston 2018-08-24 22:09:25 UTC
I didn't understand (at first) the "appears to expose undefined names".

What it does when "runpdfbegin" stops is that it leaves GS_PDF_ProcSet on
the dict stack, and apparently the "CS" proc in that causes a segfault.

The GS_PDF_ProcSet is currently in userdict, and items can be loaded from it.

A more serious issue is that the dictionary is DANGEROUS, so I have changed
this to P1, critical. I have a PoC that allows access to systemdict, so pretty
much anything can be done.

We need to make sure this dictionary isn't left laying around in userdict,
and make sure the PDF interpreter never leaves it (or other PDF interpreter
procset dicts) on the dict stack after an error, and (for extra precaution)
make it executeonly.

As a lower priority, we may want to scan the various procs to make sure that
none of them can cause segfaults (as CS does in this example).
Comment 2 Tavis Ormandy 2018-08-24 22:51:14 UTC
Ah-ha, that explains it, thanks for investigating Ray.

I guess I'm lucky CS segfaults, or I wouldn't have noticed a serious issue :)
Comment 3 Chris Liddell (chrisl) 2018-08-25 07:01:41 UTC
Presumably, if we make all the PDF interpreter procedures executeonly then that would ameliorate the worst of the exploit - it still leaves the segfault to solve, of course.

FWIW, I *suspect* the problem is that it has been assumed that binding all the PDF interpreter procedures provides security against such exploits - but bind is not guaranteed to succeed, so we shouldn't rely on it.
Comment 4 Ken Sharp 2018-08-25 07:40:44 UTC
(In reply to Chris Liddell (chrisl) from comment #3)
> Presumably, if we make all the PDF interpreter procedures executeonly then
> that would ameliorate the worst of the exploit - it still leaves the
> segfault to solve, of course.
> 
> FWIW, I *suspect* the problem is that it has been assumed that binding all
> the PDF interpreter procedures provides security against such exploits - but
> bind is not guaranteed to succeed, so we shouldn't rely on it.

As we discovered on Thursday.... Oh well.

I was going to suggest that we should make the executable procedures executeonly, I'll look at it on Monday. And yes, I wanted to understand the seg fault before hiding the problem, as in the gssetresolution case.

By the way, I don't really think its worth changing the priority or severity of these, they are all classified as 'security' which to my mind makes them as important as its possible to get.
Comment 5 Ken Sharp 2018-08-27 10:38:29 UTC
Commit ea735ba37dc0fd5f5622d031830b9a559dec1cc9 addresses the bug described here (and a similar companion possibility with the SC PDF operator).

Because Ray's comment #1 is a completely different problem, I've chose to open a new bug for that. This is bug 699676