Cover V10, I02

feb2001.tar


Listing 3 Complete working version of CGI script with taint checking

#!/usr/bin/perl -T

# Set PATH to a known good value.
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';

# Get the value of the QUERY_STRING environment variable, which is 
# set by the web server to the value of the query string portion of 
# the URI.
$querystring = $ENV{'QUERY_STRING'};

# Separate the key=val pairs into tokens.  They are delimited by &.
@qs = split (/&/, $querystring);

# Split each of the key=val pairs and save in a hash, keyed by key.
foreach $i (0 .. $#qs)
  {
    # Convert plus to space, and convert %hh to the real value.
    $qs[$i] =~ s/\+/ /g;
    $qs[$i] =~ s/%(..)/pack("c",hex($1))/ge;

    # Now, split along the =.
    ($key, $val) = split (/=/, $qs[$i], 2);

    # Untaint $val since it's going to be passed to the shell.  The 
    # regular expression match being performed here returns TRUE only
    # if $val consists entirely of these characters:  A-Z, a-z, # -,
    # @, and '.'.
    # If $val consists entirely of these characters, then $1 is set 
    # by the regular expression match to the value that matched.  
    # Since $1 is the result of a regular expression match, it is 
    # considered "laundered".
    # Set $val to $1, and now $val is laundered.
    #
    if ($val =~ /^([\w+\-@\.]*)$/)
      {
        $val = $1;
      }
    else
      {
        die "Bad value for parm = $val";
      }

    # Save in hash.
    $param{$key} = $val;
  }

# Get the value of the 'parm' key.
$parm = $param{'parm'};

# Since this CGI script is outputting plain text tell the browser
# to expect plain text.
print "Content-type: text/plain\n\n";

# Run a whois query.
print `/bin/whois $parm`;

# Done!
exit;