Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Reading ENV variable and using that in taint mode

by sara2005 (Scribe)
on Jun 27, 2006 at 19:33 UTC ( [id://557860] : perlquestion . print w/replies, xml ) Need Help??

sara2005 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

Assuming that some ENV variables are already set in the shell, I would like to use them in my CGI with the taint mode.

I get a directory path from an ENV variable (in the example, I set the env var and then grab it), add the userid, do a change directory and finally execute a system command.

I got "Insecure dependency..", "Insecure $ENV{PATH}","Insecure $ENV{ENV}" errors initially. I modifed the script after reading the perlsec documentation and several other related posts in

Below is the modified code, which works fine, but I am not sure if this is the way to go.

Your comments/suggestions would be great.


Zaxo: Thanks for the comments on the original post

I went one step further....

Instead of hardcoding the commands to execute, I read from a file, did a taint check and passed it to the 'system' command but it fails with "Insecure dependency in system while running with -T switch at ... line 63"... It is failing at system ( $runcmd );

Any suggestions? Below is the updated code...

#! /path/to/perl -wT use strict; # not used #delete @ENV{ 'IFS', 'CDPATH', 'ENV', 'BASH_ENV' }; my $workdir; my ($t_runcmd, $runcmd); # Set Work Directory env variable my $username = "thisuser"; $ENV{WORKDIRECTORY} = "/path/to/dir/$username"; # Assign env var value to tainted variable name my $t_workdir=$ENV{WORKDIRECTORY}; # Check if the variable is tainted if ( is_tainted($t_workdir) ){ $workdir = $t_workdir; } # Set default allowed paths my @allowed_paths = ( "/bin", "/usr/bin" ); # Push new workdir to allowed paths push @allowed_paths, "$workdir/bin"; # Add allowed paths to PATH $ENV{PATH} = join( ':', @allowed_paths ); print "$ENV{PATH}\n"; chdir $workdir or die "Cannot change to $workdir: $!\n"; # Open the file commands in the workdir open ( F, "$workdir/commands"); $t_runcmd = <F>; if ( is_cmd_tainted($t_runcmd) ){ $runcmd = $t_runcmd; } # Assign command -- Disabled # my $runcmd = "ls -l > test.text"; print "$runcmd\n"; # Exec command system ( $runcmd ); # I got this sub from perlsec but I have no clue as # to how this untaints the data. Hence, used one to suit my # requirement #sub is_tainted{ # return ! eval { eval("#" . substr(join("", @_), 0, 0)); 1}; #} sub is_tainted{ my $var_to_chk = shift; print "---$var_to_chk---\n"; if ( $var_to_chk =~ /^([\w\/]+)$/ ) { return 1; } else{ die "Bad path!!!\n"; } } sub is_cmd_tainted{ my $cmd_var = shift; print "---$cmd_var---\n"; # presently, the regex checks only if the command # starts with 'ls' if ( $cmd_var =~ /^(ls)+/ ) { return 1; } else{ die "Bad commands!!!\n"; } }

Replies are listed 'Best First'.
Re: Reading ENV variable and using that in taint mode
by Zaxo (Archbishop) on Jun 27, 2006 at 19:53 UTC

    Yes, setting the %ENV values you want to use within the program is exactly how to untaint them. Your method is a little more elaborate than I would usually use, but it looks fine to me.

    Rather than arrays, I would probably work directly with the strings. The arrays have some nice features, though.

    You can avoid the need to detaint PATH by using the absolute location of /bin/ls, which is unix standard.

    After Compline,

      I included /bin to $ENV{PATH} in the script but I still got the error

      I still like to use it this way so that I can run some executables by reading from a file

      Any thoughts?

        What I meant is that if you say (in the original code)

        my $runcmd = '/bin/ls -l > test.text';
        then you don't have to worry about the taintedness of PATH. It won't be used to find ls.

        After Compline,

        Include full path