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;
|