Introduction to Perl's Taint Mode (2/2) | WebReference

Introduction to Perl's Taint Mode (2/2)

current pageTo page 2

Introduction to Perl's Taint Mode

The Environment is Tainted

I mentioned earlier that variables that are set with values that are retrieved from outside of your script will be considered tainted. This is true both of variables that you are explicitly setting within your script, as well as variables that you inherit that were set from information outside the script. Among the key variables affected in this way are the environment variables (i.e., accessed through the %ENV hash), and one particular environment variable that deserves special mention in this regard is the PATH environment variable.

Since your system calls rely on the setting of the PATH variable (i.e., the command itself will be found based on the PATH setting), when Taint Mode is on Perl will not let you execute system, exec, or backtick (`OScommand`) calls unless you first explicitly set the PATH within your script. Not only this, the PATH that you set must include directories that are writable only by their owner users and owner group, not by all users. In many cases, scripts with Taint Mode enabled will simply clear the path, like this:

$ENV{"PATH"} = "";
# following would be an error if taint 
# mode is enabled and path wasn't explicitly
# set or cleared
print `/usr/opt/echo "Hello World!"`;

The reason for this is that it may be possible that a malicious user has reset your path to point to a set of dubious applications that have the same names as the common applications that you are referring to within your script. Thus, your script may find--and execute--those malicious applications unwittingly. Note that Perl doesn't care if you refer to the application with a fully qualified pathname, either; it will still disallow the action if the PATH hasn't been cleaned. This is because Perl doesn't know what the application you are accessing will do with the faulty PATH setting; thus it defaults to being overly protective and refusing the operation entirely.

In some environments, you may also need to clear or set the following variables before executing system calls, as they also can have an effect on how the system call is processed:

One other environment-related concern is worth mentioning here. As I discussed in an earlier tutorial that introduced you to the use of modules in Perl scripts, the @INC array includes a list of directories that Perl will use to search for the modules used within your script. When Taint Mode is enabled, Perl automatically removes the dot (".") entry from this list; so that the search mechanism will not automatically search the current directory for required library files (again, a malicious user could slip a dubious module with the same name in your current directory that could be loaded instead of the one you intended). For similar reasons, the PERL5LIB and PERLLIB environment variables will be ignored. Finally, if you assign to @INC a new directory that is the result of a tainted variable, then you will receive an "Insecure Dependency..." error.

Other Taint Mode Tidbits

In no paticular order, here are some last minute taint tips and facts that may be useful and/or trip you up if you aren't aware of them.

Perl 5.8 Enhancements

Beginning with version 5.8 of Perl, you can execute your script with a version of Taint Mode that will just report insecure operations as warnings, as opposed to crashing the script. You do this by using a lower case -t instead of the normal upper case -T. This feature could be used to debug an application; but it shouldn't be used in production scripts, where it's better to be safe and simply disallow tainted operations entirely.

Also in Perl 5.8, the variable ${^TAINT} can be accessed to tell you whether or not your script is running in Taint Mode.

Input is Tainted

In earlier examples I demonstrated how command line arguments, Web form arguments, and environment variables are all considered tainted by Perl when Taint Mode is activated; but these are not the only references that are tainted. As listed in perlsec, others include locale information and the expressions that it affects; results from readdir() and readlink(); the variable of shmread(); the messages returned by msgrcv(); the password, gcos and shell fields returned by getpwxxx() calls and all file input. Thus, any data you read in from a file is by default tainted.

Some Things You Might Not Expect

Symbolic References not Taint Checked

Variable values used as symbolic method and subroutine references (as well as the arguments passed to such routines) are not checked for taintedness before the referenced routine is called, i.e.:

my $foo = shift;
# though tainted, the routine referenced by name in 
# $foo will be executed, with the remaining arguments
# passed from the command line. 

Though the code executed as the result of the symbolic reference will itself check the taintedness of any variables it relies on, such a construct as above could still be used by an attacker to branch your program off in directions you did not intend; with no warnings from Taint Mode.

Ternary Operator Sub Expressions Not (Necessarily) Tainted

Earlier we mentioned that any variables in a subexpression of an expression that involves tainted data will themselves be tainted; but this does not apply to expressions in a ternary operation (unless the sub-expression in the ternary operation refers to the tainted variable). I.E.:

my $foo = shift;
# After the next statement, $bar is 
# not tainted, even though $foo is
my $bar = ($foo=~/bar/) ? "foobar" : "nobar";
# However, after this statement $bar will be 
# tainted if $foo contains "bar" but not 
# otherwise
$bar = ($foo=~/bar/) ? $foo : "nobar";
print and syswrite Allowed

Though you can't open a file for writing where the name is provided via a tainted variable, you can write tainted data to any file. I.E., this will crash in taint mode:

my $foo = shift;
open (MYFILE, ">$foo");

But this is allowed:

my $foo = shift;
open (MYFILE, ">somefile.txt");
print MYFILE $foo;


As mentioned earlier, Perl's Taint Mode will not, in and of itself, force you to write secure scripts; but it may force you to at least think about the security of your script (as well as prevent you from unknowingly introducing some known security risks). I encourage you to take advantage of this built-in security mechanism within your own scripts.

current pageTo page 2

Created: April 18, 2006
Revised: May 5, 2006