Search code examples
perltaint

Why doesn't a pipe open work under Perl's taint mode?


My original script is as follows:

my $cmd = "dir";
open (H, "$cmd |");
my @result = <H>;
close (H);
print STDERR @result,"\n";

This scripts works fine. If I add following line to the script, it fails to work:

$ENV{"LD_LIBRARY_PATH"} = "/opt/VRTSsfmh/lib";
$ENV{PATH}="/usr/bin:/bin:/sbin:/usr/sbin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

What does Perl use when pipe open is called?

Addition of following code fixed the issue:

if ($^O =~ /Win32/i) 
{
    $ENV{'SystemRoot'} =~ /([A-Z]:(\\[A-Za-z0-9_]+)+)/;
    my $system32_dir = $1."\\system32";
    $ENV{'PATH'} = $system32_dir;
}

Solution

  • Your question is not really related to taint mode. You set

    $ENV{PATH}="/usr/bin:/bin:/sbin:/usr/sbin";
    

    These directories do not normally exist on a Windows machine. dir is a cmd.exe internal command so to be able to execute that, you need to add the directory where it resides to the path.

    Now, note that the way you go about doing it contradicts the whole point of setting the path to known definite locations. It is definitely possible for a nefarious user to change this environment variable to point to his dangerous version of dir.

    The fact that Windows is not necessarily installed in C:\Windows complicates writing a taint-safe script on Windows if you rely on any of the shell builtins.

    EDIT: Here is a short test program you can use as a baseline:

    #!/usr/bin/perl -T
    
    use strict;
    use warnings;
    
    $ENV{PATH} = join(';', qw(C:\Windows C:\Windows\System32) );
    delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
    
    open my $pipe_h, '-|', 'dir'
        or die "Cannot open pipe to dir: $!";
    
    print while <$pipe_h>;
    
    close $pipe_h
        or die "Cannot close pipe to dir: $!";
    
    __END__
    
    C:\Temp> perl -T v.pl
    
    ...
    
    2009/05/25  08:58 AM             3,584 zzz.exe
                  64 File(s)     32,125,365 bytes
                  14 Dir(s)  39,251,894,272 bytes free
    

    Basically, what you need is for the system administrator to hardcode the acceptable path at installation time and for untrusted users not to have write permissions on the script.