COMMAND

    uncgi

SYSTEMS AFFECTED

    uncgi

PROBLEM

    Khamba Staring posted  following.  He  recently found a  number of
    vulnerabilities in the CGI wrapper program `uncgi'.

    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.

SOLUTION

    Patch:

    --- 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__ /* { */

    Author released a fix for the ../ hole:

        http://www.midwinter.com/~koreth/uncgi.html

    has a link to the new version.  Adding relative directory checking
    beyond that  would have  little security  benefit.   The following
    two-line shell script demonstrates why:

        #!/bin/sh
        /run/a/malicious/program/somewhere/else

    Put that script  in Un-CGI's script  directory and you're  off and
    running.   If  you  can  put  a  symbolic  link  into  the  script
    directory,  you  can  put  a  script  like  this there instead, so
    blocking  symbolic  links  doesn't  make  your system particularly
    more secure.

    With the exception of the  ../ hole, Un-CGI's security is  exactly
    the  same  as  the  security  of  your  script  directory.  Which,
    really,  when  you  think  about  it,  is  also  true of a typical
    CGI-capable Web  server; as  soon as  you let  random users  stick
    programs in the  cgi-bin directory you're  opening yourself up  to
    potential security problems.