httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Randy Terbush <ra...@zyzzyva.com>
Subject Re: setuid control WITHOUT running as root
Date Sun, 02 Jun 1996 20:42:27 GMT
> > > I personally think it would be better to design any CGI modifications
> > > (along the lines of suCGI) without thinking about setuid purposes...
> >
> > My approach is really no different than that of mod_sucgi. One advantage
> > of my approach is that it centralizes the exec code where some of the
> > initial safety checks are done. It is then easy for anything else in the
> > server to use call_exec() to do the job.
> 
> Right, but a misconfigured sucgi.c is then a MAJOR security hole... A
> misconfigured cgiwrap for example just won't work...

There really isn't much in this wrapper that can be misconfigured.
I'm for keeping it as simple as possible.

> Your patch would be an excellent solution, but I think that sucgi.c needs
> to have some security checks built into it as well...

There are a fair number of checks in sucgi already. I'll include the
latest massaging below. I've applied the Apache Copyright. Jason can
elect to remove that if he wishes since it was is code I started with.

Realizing that you (Nathan, the author of CGIWrap) is on the list,
it would be helpful to have your eyes look this over since you are
pretty familiar with this type of wrapper.

> > > This would isolate the Apache server from the major security concerns of
> > > running setuid scripts and such, but at the same time would allow that
> > > functionality to be added much more easily with add-on tools produced by
> > > other people.
> >
> > How does my patch fail to address that?
> 
> The problem of the sucgi.c backend still being somewhat of a hole.

Take another look. It's *very* simple. It does manage to arrest
the main complaint of my previous suggestions by removing the
need to run EUID root Apache. I've added a logfile to help catch
the bad guys and disabled it's ability to execute a setuid(0) or
setgid(0) request. You can't pass an argument with an absolute 
path. I suppose that refusing to execute symlinks would also be
in order. 



/* ====================================================================
 * Copyright (c) 1995 The Apache Group.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * 4. The names "Apache Server" and "Apache Group" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission.
 *
 * 5. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Group and was originally based
 * on public domain software written at the National Center for
 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
 * For more information on the Apache Group and the Apache HTTP server
 * project, please see <http://www.apache.org/>.
 *
 */

/*
 *
 * sucgi.c -- "wrapper" support program for mod_sucgi for Apache
 *
 * A MotherSoft Product for the Apache WWW server.
 * (http://www.louisville.edu/~jadour01/mothersoft/)
 *
 * Codebase originally from Majordomo(v1.93) release.  Modifications
 * by Jason A. Dour (jadour01@homer.louisville.edu).
 *
 * NOTE! : Due to the sensitive nature of this program, its error messages
 *         are left intentionally unhelpful...
 *
 * HTTPD_USER - Set this to the username that is allowed to execute
 *             this program.  Most likely, it's some generic user
 *             such as 'httpd' or some such...
 *
 * Version 0.0.1 - Randy Terbush (randy@zyzzyva.com)
 * First assigned version. Heavily modified to act as generic SUID wrapper for
 * Apache.
 *
 */

#define HTTPD_USER "www"
#define LOG_EXEC "/www/var/log/vh_master/cgi.log"

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
#include <strings.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>


static void
err_output (const char *fmt, va_list ap)
{
    time_t timevar;
    struct tm *lt;
    FILE *log;

    log = fopen (LOG_EXEC, "a");

    time (&timevar);
    lt = localtime (&timevar);
    
    fprintf (log, "[%.2d:%.2d:%.2d %.2d-%.2d-%.2d]: ", lt->tm_hour, lt->tm_min,
	     lt->tm_sec, lt->tm_mday, lt->tm_mon, lt->tm_year);
    
    vfprintf (log, fmt, ap);

    fflush (NULL);
    fclose (log);
    return;
}

void
log_err (const char *fmt, ...)
{
#ifdef LOG_EXEC
    va_list     ap;

    va_start (ap, fmt);
    err_output (fmt, ap);
    va_end(ap);
#endif
    return;
}

int
main(int argc, char *argv[], char **env)
{
    uid_t uid;
    struct passwd *pw;
    struct group *gr;

    uid = getuid();
    if ((pw = getpwuid (uid)) == NULL)
    {
	log_err ("(%s): error code 1 (%ld)\n", argv[0], uid);
	exit (101);
    }
    
    if (strcmp (HTTPD_USER, pw->pw_name))
    {
        log_err ("(%s): error code 2 (%s)\n", argv[0], pw->pw_name);
        exit(102);
    }
    
    if (argc < 4)
    {
	log_err ("(%s): error code 3\n", argv[0]);
	exit(103);
    }

    if ( strchr(argv[3], '/') != (char) NULL )
    {
        log_err ("(%s): error code 4 (%s)\n", argv[0], argv[3]);
        exit(104);
    }

    pw = getpwnam (argv[1]);
    if (pw->pw_uid == 0)
    {
        log_err ("(%s): error code 5 (%d)\n", argv[0], argv[3]);
        exit(105);
    }
	
    if (setuid(pw->pw_uid) != 0)
    {
        log_err ("(%s): error code 6 (%d)\n", argv[0], pw->pw_uid);
        exit(106);
    }

    gr = getgrnam (argv[2]);
    if (gr->gr_gid == 0)
    {
        log_err ("(%s): error code 7 (%d)\n", argv[0], argv[3]);
        exit(107);
    }
	
    if (setgid(gr->gr_gid) != 0)
    {
        log_err ("(%s): error code 8 (%d)\n", argv[0], gr->gr_gid);
        exit(108);
    }

    execve(argv[3], &argv[4], env);

    log_err ("(%s): error code 255 (%s)\n", argv[0], argv[3]);
    exit(255);
}












Mime
View raw message