[UNIX] GV Execution of Arbitrary Shell Commands (Additional details)

From: support@securiteam.com
Date: 10/03/02


From: support@securiteam.com
To: list@securiteam.com
Date: Thu,  3 Oct 2002 23:14:38 +0200 (CEST)

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

When was the last time you checked your server's security?
How about a monthly report?
http://www.AutomatedScanning.com - Know that you're safe.
- - - - - - - - -

  GV Execution of Arbitrary Shell Commands (Additional details)
------------------------------------------------------------------------

SUMMARY

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 chosen filename, that can even seems innocent)
that causes execution of arbitrary shell commands when it is read with GV.

DETAILS

Vulnerable systems:
 * gv-3.5.8 and probably older versions

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

 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
resource):
"gs -dNODISPLAY -dQUIET -sPDFname=%s -sDSCname=%s pdf2dsc.ps -c quit"
The first "%s" corresponds to the PDF filename, and the second 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 resource):
"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.

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

 o a PDF file named 'Huhu_"`source evil`".pdf' (double quotes and back
quotes 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 (for example 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 has not 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' built-in; that's the case when /bin/sh is a link to
bash.

Solution:
The GV maintainer, <mailto:plass@thep.physik.uni-mainz.de> Johannes
Plass, 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, Marc 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.

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 developed: see the attached patch done against GV
3.5.8.

Attached files:
The following file is also available at:
 <http://www.epita.fr/~bevand_m/asa/asa-0000.gv-3.5.8.patch>
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 -------------------------

ADDITIONAL INFORMATION

References:
[0] GV <http://wwwthep.physik.uni-mainz.de/~plass/gv/>
http://wwwthep.physik.uni-mainz.de/~plass/gv/

[1] Ghostscript <http://www.cs.wisc.edu/~ghost/index.html>
http://www.cs.wisc.edu/~ghost/index.html

[2] GNU Zip <http://www.gzip.org> http://www.gzip.org

The advisory can be also downloaded from:
 <http://www.epita.fr/~bevand_m/asa/asa-0000>
http://www.epita.fr/~bevand_m/asa/asa-0000

The information has been provided by <mailto:bevand_m@epita.fr> Marc
Bevand.

========================================

This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • [Full-Disclosure] [ GLSA 200408-14 ] acroread: UUDecode filename buffer overflow
    ... that may lead to execution of arbitrary code or programs. ... acroread is Adobe's Acrobat PDF reader for Linux. ... it fails to check the length of a filename before copying it ... Security is a primary focus of Gentoo Linux and ensuring the ...
    (Full-Disclosure)
  • [ GLSA 200408-14 ] acroread: UUDecode filename buffer overflow
    ... that may lead to execution of arbitrary code or programs. ... acroread is Adobe's Acrobat PDF reader for Linux. ... it fails to check the length of a filename before copying it ... Security is a primary focus of Gentoo Linux and ensuring the ...
    (Full-Disclosure)
  • [ GLSA 200408-14 ] acroread: UUDecode filename buffer overflow
    ... that may lead to execution of arbitrary code or programs. ... acroread is Adobe's Acrobat PDF reader for Linux. ... it fails to check the length of a filename before copying it ... Security is a primary focus of Gentoo Linux and ensuring the ...
    (Bugtraq)
  • Re: PDF security
    ... r> I am aware of the security features for protecting PDFs from within ... PDF security is standardized, i.e. all the existing PDF implementations use ... I think that the most secure solution for you is to certify your magazine ...
    (comp.text.pdf)
  • PDF four versions of a document then delete interim saved Word files
    ... PDF file and I'd only end up with one. ... When I create the file I initially save it with a compound filename, ... consisting of a filename string the user provides (I put up a dialog box ... Technical Writer - Online Help Developer - Technical Illustrator ...
    (microsoft.public.word.vba.customization)