Bugtraq mailing list archives

multiple vulnerabilities in un-cgi


From: Khamba Staring <purrcat () edoropolis org>
Date: Tue, 17 Jul 2001 12:48:12 +0200


I recently found a number of vulnerabilities in the CGI wrapper program
`uncgi'. I was amazed to find out this was never reported before (at least;
the archives don't show it).

Description
-----------

Un-CGI is a little program that parses options in i.e. QUERY_STRING and
starts a CGI script. Since all parsing is done by uncgi, the CGI scripts
themselves are simple and quick to make (all options/variables passed to
the CGI script via the URL are translated into seperate environment
variables). It is possible to run uncgi as a stand-alone executable or
use it in library form. The problems described in this post are located
in the executable, not the library.

1. uncgi does no relative directory checking; this means anyone can
   execute any program on the remote system as the http user (to some
   extent, permission wise of course) using the simple dot-dot-slash trick.
2. uncgi does not check if the script it will execute has any executable
   bits turned on. As most CGI scripts are just that-- scripts, uncgi
   will try to execute the program located behind #! on the first line
   of the CGI script and feed the CGI script filename itself as an
   argument. This means the CGI script doesn't have to be executable
   for uncgi to be able to execute it.


Two very serious matters; I mailed the writer @midwinter.com and he
was kind enough to add a little `bugs' section to his uncgi page. However,
I don't believe _that_ will change much. As these vulnerabilities are
so easy to exploit, I almost know for sure these vulnerabilities are
already being exploited.
Don't get mad at me; I just want this to become known so things will
get fixed. I attached a patch which should fix the problems I pointed
out in this post. This patch will almost certainly break things on
insecure websites.


Kind regards,

-- Khamba Staring

-----------------------------------------------------------------------------
--- uncgi.c.old Thu Jul 12 12:42:09 2001
+++ uncgi.c     Thu Jul 12 13:24:35 2001
@@ -60,6 +60,14 @@
 
 char *id = "@(#)uncgi.c        1.33 11/24/97";
 
+
+void four_oh_three()
+{
+  printf("Content-Type: text/htm\n\n");
+  printf("You have no permission!\n");
+  exit(1);
+}
+
 /*
  * Convert two hex digits to a value.
  */
@@ -373,6 +381,18 @@
     char    *shell, *script;
 {
        char    *argvec[4], **ppArg = argvec, *pz;
+       struct stat f_stat;
+
+       if(stat(script, &f_stat) == -1)
+         html_perror("stat (something like this; dunno what html_perror does exactly)");
+
+/*
+** this should probably be expanded a bit; maybe check for S_IXUSR, S_IXGRP
+** and S_IXOTH or the likes. Maybe add extra checks for suid or let the
+** shell figure that out?
+*/
+       if(!(f_stat.st_mode & S_IXUSR))
+         html_perror("not executable");
 
        /*
         *  "shell" really points to the character following the "#!",
@@ -542,6 +562,21 @@
 #endif
 }
 
+int check_path(char *evilpath)
+{
+#define RP_PATHLEN 1024
+  char resolved_path[RP_PATHLEN];
+
+  if(!realpath(evilpath, resolved_path))
+    return(0); /* evil path cannot be read; this can't be good! */
+
+  if(strncmp(SCRIPT_BIN, resolved_path, strlen(SCRIPT_BIN) - 1) == 0)
+    return(1); /* yay! */
+  else
+    return(0); /* boo! */
+}
+
+
 #ifndef LIBRARY /* { */
 main(argc, argv)
        int     argc;
@@ -600,6 +635,11 @@
                strcpy(program, SCRIPT_BIN);
                strncat(program + sizeof(SCRIPT_BIN) - 1, pathinfo, proglen);
 
+#ifndef VOID_SECURITY
+               if(!check_path(program))
+                       four_oh_three();
+#endif
+
 #ifdef DEBUG
                printf("Program path is '%s'\n", program);
                fflush(stdout);
@@ -700,6 +740,9 @@
         */
        argvec[0] = program;
        argvec[1] = NULL;
+/*
+** shouldn't we check for suid stuff here?!
+*/
        execv(program, argvec);
 
 #ifdef __MSDOS__ /* { */


Current thread: