-2

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
user3066571
  • 1,381
  • 4
  • 14
  • 37
  • 2
    Can't reproduce the problem with the code you posted. Needs more [mcve]. – melpomene Apr 22 '18 at 19:05
  • 3
    Taint complains about insecure dependency when the value sent to the system (probably $date here) has a value coming from outside of the source, i.e. from a file or user input. Are you sure $date isn't populated by a form? – choroba Apr 22 '18 at 19:08
  • @choroba the user enters in a parameter in a form, that in perl I have to do transforms on before assigning it to `$date`. I updated the post to reflect this. – user3066571 Apr 22 '18 at 19:23
  • 2
    “transforms before assigning it to $date” – these exact transforms matter very much! In most cases where the `$param` value is transformed into `$date`, the new value will also be tainted. Please show the relevant code, or we can't tell you why these transformations are tainting the `$date`. The pseudocode you've shown so far is insufficient. – amon Apr 22 '18 at 19:38
  • @amon I put the whole actual script in. – user3066571 Apr 22 '18 at 19:46
  • 1
    Oh hello, it's the broken regex code from https://stackoverflow.com/q/49969831/1848654. – melpomene Apr 22 '18 at 19:49
  • @melpomene hey buddy, I was trying to tackle 2 separate issues, nice to see you. – user3066571 Apr 22 '18 at 19:49
  • @user3066571 Why do you think they're separate? – melpomene Apr 22 '18 at 19:56
  • @melpomene the other one was about my broken regex, and this one was about the `Insecure dependency` error. Maybe they're relatd, I clearly don't know. – user3066571 Apr 22 '18 at 19:58

1 Answers1

4

$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.

amon
  • 57,091
  • 2
  • 89
  • 149
  • The `$foo = /bar/` issue was asked by the OP [here](https://stackoverflow.com/q/49969831/9300627). – haukex Apr 22 '18 at 20:01
  • This is exactly what I needed, thank you. And you fixed my broken-as-balls regex while you were at it. Thanks so much. – user3066571 Apr 22 '18 at 20:12