I have a script running strict with the -T parameter or 'taint' mode. If I try to set the value of a variable already defined, it craps out. I didn't make much of it, I'm just trying to modify it and don't know why it's breaking. Here's the gist of what it looks like:
#!/usr/bin/perl -T
use 5.010;
use CGI;
use CGI::Carp qw/fatalsToBrowser/;
use strict;
use warnings;
use localtime;
my @months = qw(january february march april may june july august september october november december);
my $q = CGI->new();
say $q->header(), $q->start_html(-title=>'Calendar');
for my $param ($q->param()) {
my $safe_param = $q->escapeHTML($param);
for my $value ($q->param($param)) {
my $params = $q->escapeHTML($value);
{
local $ENV{"PATH"} = "/bin:/usr/local/bin:/usr/bin";
local $ENV{"BASH_ENV"}="";
my $date = "";
my $white = /^\s*$/;
my $singleyear = /^\d{2,4}$/;
my $nummonth = /^\d{1,2}\s\d{1,4}$/;
# If $params is empty or all white space, set $date to a single space
if ($params =~ $white) {
my($day, $month, $year)=(localtime)[3,4,5];
my $monthname = $months[$month];
$date = "$monthname $year"
}
# If $params is only a single 1-4 digit year, set $date to year
if ($params =~ $singleyear) {
$date = $params;
}
# If $params is a 1-2 digit month and a 1-4 digit year set $date to month and year
if ($params =~ $nummonth) {
my $monthnumber = $params =~ /^\d{1,2}/;
my $monthstring = $months[$monthnumber];
my $yearnumber = $params =~ /(\d{1,4})$/;
$date = "$monthstring $yearnumber";
}
if ($date eq "") {
say "<h1>Invalid Parameters: $params</h1>";
} else {
say "<h1>Parameters: $params</h1>";
}
my $cmds = "cal -h " . $date;
my @lines = `$cmds`;
say ("<pre>");
for my $line (@lines) {
print ("$line");
}
say ("</pre>");
}
}
say '</p>';
}
say $q->end_html();
At any point I set the value of $date
it throws the error:
Insecure dependency in `` while running with -T switch
if I set my $date
it throws no error, but doesn't actually update the value of date.
Also, I'm pretty sure all my regex is wrong, because I did some testing, and all of those cases evaluate to true for some reason, regardless of the user input. But that's not really the problem I'm facing now.
Example user input for $params
02 1999
$date = $params;
Such code assigns the tainted $params
value to $date
without untainting it.
Instead: Match the exact data you want with a regex, and use regex captures to extract an untainted value. For example:
if ($params =~ /^(\d{2,4})$/) {
$date = $1;
}
And so on for the other cases.
Note that assigning a regex $foo = /bar/
does not assign a regex object, but assigns the result of matching that regex against the $_
variable! If you need to create regex objects, use the qr/.../
operator. However, using regex objects seems unnecessary in your program – just write down the regex in each condition in order to avoid problems.