- publishing free software manuals
Perl Language Reference Manual
by Larry Wall and others
Paperback (6"x9"), 724 pages
ISBN 9781906966027
RRP £29.95 ($39.95)

Sales of this book support The Perl Foundation! Get a printed copy>>>

22.2.1 Taint mode

Perl automatically enables a set of special security checks, called taint mode, when it detects its program running with differing real and effective user or group IDs. The setuid bit in Unix permissions is mode 04000, the setgid bit mode 02000; either or both may be set. You can also enable taint mode explicitly by using the -T command line flag. This flag is strongly suggested for server programs and any program run on behalf of someone else, such as a CGI script. Once taint mode is on, it's on for the remainder of your script.

While in this mode, Perl takes special precautions called taint checks to prevent both obvious and subtle traps. Some of these checks are reasonably simple, such as verifying that path directories aren't writable by others; careful programmers have always used checks like these. Other checks, however, are best supported by the language itself, and it is these checks especially that contribute to making a set-id Perl program more secure than the corresponding C program.

You may not use data derived from outside your program to affect something else outside your program--at least, not by accident. All command line arguments, environment variables, locale information (see "Perl locale handling (internationalization and localization)" (perllocale) in the Perl Unicode and Locales Manual), results of certain system calls (readdir(), readlink(), the variable of shmread(), the messages returned by msgrcv(), the password, gcos and shell fields returned by the getpwxxx() calls), and all file input are marked as "tainted". Tainted data may not be used directly or indirectly in any command that invokes a sub-shell, nor in any command that modifies files, directories, or processes, with the following exceptions:

For efficiency reasons, Perl takes a conservative view of whether data is tainted. If an expression contains tainted data, any subexpression may be considered tainted, even if the value of the subexpression is not itself affected by the tainted data.

Because taintedness is associated with each scalar value, some elements of an array or hash can be tainted and others not. The keys of a hash are never tainted.

For example:

$arg = shift;               # $arg is tainted
$hid = $arg, 'bar';         # $hid is also tainted
$line = <>;                 # Tainted
$line = <STDIN>;            # Also tainted
open FOO, "/home/me/bar" or die $!;
$line = <FOO>;              # Still tainted
$path = $ENV{'PATH'};       # Tainted, but see below
$data = 'abc';              # Not tainted
system "echo $arg";         # Insecure
system "/bin/echo", $arg;   # Considered insecure
                            # (Perl doesn't know about /bin/echo)
system "echo $hid";         # Insecure
system "echo $data";        # Insecure until PATH set
$path = $ENV{'PATH'};       # $path now tainted
$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$path = $ENV{'PATH'};       # $path now NOT tainted
system "echo $data";        # Is secure now!
open(FOO, "< $arg");        # OK - read-only file
open(FOO, "> $arg");        # Not OK - trying to write
open(FOO,"echo $arg|");     # Not OK
open(FOO,"-|")
    or exec 'echo', $arg;   # Also not OK
$shout = `echo $arg`;       # Insecure, $shout now tainted
unlink $data, $arg;         # Insecure
umask $arg;                 # Insecure
exec "echo $arg";           # Insecure
exec "echo", $arg;          # Insecure
exec "sh", '-c', $arg;      # Very insecure!
@files = <*.c>;             # insecure (uses readdir() or similar)
@files = glob('*.c');       # insecure (uses readdir() or similar)
# In Perl releases older than 5.6.0 the <*.c> and glob('*.c') would
# have used an external program to do the filename expansion; but in
# either case the result is tainted since the list of filenames comes
# from outside of the program.
$bad = ($arg, 23);          # $bad will be tainted
$arg, `true`;               # Insecure (although it isn't really)

If you try to do something insecure, you will get a fatal error saying something like "Insecure dependency" or "Insecure $ENV{PATH}".

The exception to the principle of "one tainted value taints the whole expression" is with the ternary conditional operator ?:. Since code with a ternary conditional

$result = $tainted_value ? "Untainted" : "Also untainted";

is effectively

if ( $tainted_value ) {
    $result = "Untainted";
} else {
    $result = "Also untainted";
}

it doesn't make sense for $result to be tainted.

ISBN 9781906966027Perl Language Reference ManualSee the print edition