Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!


TUCoPS :: Unix :: General :: unix5721.htm

GhostView Execution of Arbitrary Shell Commands



2nd Oct 2002 [SBWID-5721]
COMMAND

	GV Execution of Arbitrary Shell Commands

SYSTEMS AFFECTED

	gv-3.5.8 and probably older versions

PROBLEM

	In Marc Bevand [bevand_m (at) epita.fr] advisory :
	

	 http://www.epita.fr/~bevand_m/asa/asa-0000

	

	

	 --oOo-- 1. Introduction

	

	GV [0] is a PostScript and PDF previewer available on many unix  systems
	and even on some non-unix systems. Technically, it is a  user  interface
	for  Ghostscript  [1],  which  is  a   PostScript   and   PDF   language
	interpreter. GV is also able to  automatically  decompress  GZip'ed  [2]
	files on-the-fly before reading them.
	

	When GV detects that the document  is  either  a  PDF  file  or  a  GZip
	compressed file,  it  executes  some  commands  with  the  help  of  the
	system() function. Unfortunately, these commands contain  the  filename,
	which can be considered as untrusted user input. It is then possible  to
	distribute a file (with a meticulously choosed filename, that  can  even
	seems innocent) that causes execution of arbitrary shell  commands  when
	it is read with GV.
	

	

	 --oOo-- 2. Problem

	

	GV detects PDF files or GZip  compressed  files  by  reading  the  first
	bytes of datas:
	

	o when "%PDF-" is read, GV assumes it is a PDF file  and  call  system()
	with the following argument (default value of  the  GV.gsCmdScanPDF  X11
	ressource):
	

	 "gs -dNODISPLAY -dQUIET -sPDFname=%s -sDSCname=%s pdf2dsc.ps -c quit"

	

	The 1st "%s"  corresponds  to  the  PDF  filename,  and  the  2nd  to  a
	temporary filename.
	

	o when "\037\235" or "\037\213"  is  read,  GV  assumes  it  is  a  GZip
	compressed file and call system() with the following  argument  (default
	value of the GV.uncompressCommand X11 ressource):
	

	 "gzip -d -c %s > %s"

	

	The 1st "%s" corresponds to the GZip compressed filename,  and  the  2nd
	to a temporary filename.
	

	In these conditions, trying to open, for example, a PDF file named
	

	"xxx & echo hello & xxx" 

	

	leads to execution of
	

	"gs -dNODISPLAY -dQUIET -sPDFname=xxx & echo hello & xxx ...". 

	

	Thus,
	

	"echo hello" 

	

	(a part of the filename) is executed:
	

	      $ file "xxx & echo hello & xxx"

	      xxx & echo hello & xxx: PDF document, version 1.2

	      $ gv "xxx & echo hello & xxx" 

	  --> hello

	      sh: xxx: command not found

	      GS>hello

	      sh: xxx..tmp: command not found

	

	The error messages ("sh: xxx: command not found", etc) are just  results
	of the garbage introduced in the system() argument by the  unusual  "xxx
	& echo hello & xxx" filename. Moreover,  GV  displays  a  dialog
	box explaining that execution of Ghostscript failed.
	

	But all these "inconvenients" (from the  malicious  user  point-of-view)
	can be easily avoided. Imagine a site where  each  host  access  a  file
	server through the mount point "/sgoinfre",  and  suppose  that  someone
	(Charly) creates 2 files in this directory:
	

	  o a PDF file named 'Huhu_"`source evil`".pdf'

	(doublequotes and

	    backquotes are part of the filename)

	  o a shell script named 'evil' that contains:

	      #!/bin/sh

	      echo '"`source evil`"'

	      touch _it_works_

	

	Now, here is what happens if someone else (Alice) wants to read the  PDF
	file:
	

	  $ cd /sgoinfre

	  $ gv 'Huhu_"`source evil`".pdf'

	

	All works fine for Alice (no error  messages,  no  dialog  box),  except
	that she hasn't  realized  that  'evil'  has  been  executed  under  her
	identity:
	

	  $ ls -l _it_works_

	  -rw-------    1 alice   users         0 Jul 30 05:56 _it_works_

	

	Note: this example works only if the /bin/sh shell executed by  system()
	supports the 'source' builtin; that's the case when /bin/sh  is  a  link
	to bash.

SOLUTION

	 --oOo-- 3. Solution

	

	The     GV     maintainer,     Johannes     Plass     <plass     (at)
	thep.physik.uni-mainz.de>, has been e-mailed twice about  this  problem.
	Unfortunately, no response has been  received,  it  seems  that  he  has
	stopped his work on GV since 1997.
	

	However,   I   propose   a   temporary   fix:   the    attached    patch
	("asa-0000.gv-3.5.8.patch"),  done  against  GV  3.5.8,  checks  if  the
	filename   contains   only   allowed   characters   (alphanumeric    and
	``+,-./:=@\^_'').  If  this  is  not  the  case,  an  error  message  is
	displayed and system() is not called.
	

	 --oOo-- 4. Conclusion

	

	GV contains a  security  hole  allowing  execution  of  arbitrary  shell
	commands. Since the author seems to have  stopped  his  work  on  GV,  a
	temporary fix has been developped: see the attached patch  done  against
	GV 3.5.8.
	

	

	 --oOo-- 5. References

	

	[0] GV

	    http://wwwthep.physik.uni-mainz.de/~plass/gv/

	

	[1] Ghostscript

	    http://www.cs.wisc.edu/~ghost/index.html

	

	[2] GNU Zip

	    http://www.gzip.org

	

	 --oOo-- 6. Attached files

	

	The following file is also available at:
	

	http://www.epita.fr/~bevand_m/asa/asa-0000.gv-3.5.8.patch

	

	---8<------------------ asa-0000.gv-3.5.8.patch-------------------------

	diff -ur gv-3.5.8.orig/source/file.c gv-3.5.8/source/file.c

	--- gv-3.5.8.orig/source/file.c 1997-06-07

	00:00:00.000000000 +0200

	+++ gv-3.5.8/source/file.c      2002-09-26

	23:56:00.000000000 +0200

	@@ -285,6 +285,22 @@

	 }

	 

	 /*############################################################*/

	+/* file_nameIsDangerous */

	+/*############################################################*/

	+

	+char *file_charsAllowedInName = "+,-./:=@\\^_";

	+

	+int

	+file_nameIsDangerous(fn)

	+  char *fn;

	+{

	+  for (; *fn; fn++)

	+    if (!isalnum(*fn) &&

	!strchr(file_charsAllowedInName, *fn))

	+      return(1);

	+  return(0);

	+}

	+

	+/*############################################################*/

	 /* file_pdfname2psname */

	 /* If the file ends in .pdf, change this to .ps.*/

	 /* Return pointer to temp copy if changed, else to

	input string. */

	diff -ur gv-3.5.8.orig/source/file.h gv-3.5.8/source/file.h

	--- gv-3.5.8.orig/source/file.h 1997-04-26

	00:00:00.000000000 +0200

	+++ gv-3.5.8/source/file.h      2002-09-26

	23:28:38.000000000 +0200

	@@ -70,6 +70,14 @@

	 #endif

	 );

	 

	+extern char *file_charsAllowedInName;

	+

	+extern int                     file_nameIsDangerous (

	+#if NeedFunctionPrototypes

	+   char *

	+#endif

	+);

	+

	 extern char*                   file_pdfname2psname (

	 #if NeedFunctionPrototypes

	    char *      /* name */

	diff -ur gv-3.5.8.orig/source/ps.c gv-3.5.8/source/ps.c

	--- gv-3.5.8.orig/source/ps.c   1997-06-07

	00:00:00.000000000 +0200

	+++ gv-3.5.8/source/ps.c        2002-09-27

	00:29:35.000000000 +0200

	@@ -420,6 +420,16 @@

	       char cmd[512];

	       char s[512];

	       filename_unc=file_getTmpFilename(NULL,filename_raw);

	+      if (file_nameIsDangerous(filename))

	+       {

	+         INFMESSAGE(the filename is dangerous)

	+         sprintf(s, "The filename \"%s\" is dangerous:

	only alphanumeric "

	+                 "characters and \"%s\" are allowed.\n",

	+                 filename, file_charsAllowedInName);

	+         NotePopupShowMessage(s);

	+         ENDMESSAGE(psscan)

	+         return(NULL);

	+       }

	       sprintf(cmd,cmd_uncompress,filename,filename_unc);

	       INFMESSAGE(is compressed)

	       INFSMESSAGE(uncompress command,cmd)

	@@ -491,6 +501,16 @@

	       char cmd[512];

	       char s[512];

	       filename_dsc=file_getTmpFilename(NULL,filename_raw);

	+      if (file_nameIsDangerous(filename))

	+       {

	+         INFMESSAGE(the filename is dangerous)

	+         sprintf(s, "The filename \"%s\" is dangerous:

	only alphanumeric "

	+                 "characters and \"%s\" are allowed.\n",

	+                 filename, file_charsAllowedInName);

	+         NotePopupShowMessage(s);

	+         ENDMESSAGE(psscan)

	+         return(NULL);

	+       }

	       sprintf(cmd,cmd_scan_pdf,filename,filename_dsc);

	       INFMESSAGE(is PDF)

	       INFSMESSAGE(scan command,cmd)

	---8<------------------ asa-0000.gv-3.5.8.patch

	


TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2014 AOH