=head1 NAME
perlsec - Perl security
=head1 DESCRIPTION
Perl is designed to make it easy to program securely even when running
with extra privileges, like setuid or setgid programs. Unlike most
command line shells, which are based on multiple substitution passes on
each line of the script, Perl uses a more conventional evaluation scheme
with fewer hidden snags. Additionally, because the language has more
builtin functionality, it can rely less upon external (and possibly
untrustworthy) programs to accomplish its purposes.
=head1 SECURITY VULNERABILITY CONTACT INFORMATION
If you believe you have found a security vulnerability in Perl, please email
perl5-security-report@perl.org with details. This points to a closed
subscription, unarchived mailing list. Please only use this address for
security issues in the Perl core, not for modules independently distributed on
CPAN.
=head1 SECURITY MECHANISMS AND CONCERNS
=head2 Taint mode
Perl automatically enables a set of special security checks, called I, 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 B<-T> command line flag. This flag is
I 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 I 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
L), results of certain system calls (C,
C, the variable of C, the messages returned by
C, the password, gcos and shell fields returned by the
C 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, B:
=over 4
=item *
Arguments to C and C are B checked for taintedness.
=item *
Symbolic methods
$obj->$method(@args);
and symbolic sub references
&{$foo}(@args);
$foo->(@args);
are not checked for taintedness. This requires extra carefulness
unless you want external data to affect your control flow. Unless
you carefully limit what these symbolic values are, people are able
to call functions B your Perl code, such as POSIX::system,
in which case they are able to run arbitrary external code.
=item *
Hash keys are B tainted.
=back
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 B tainted.
For example:
$arg = shift; # $arg is tainted
$hid = $arg, 'bar'; # $hid is also tainted
$line = <>; # Tainted
$line = ; # Also tainted
open FOO, "/home/me/bar" or die $!;
$line = ; # 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 C. 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 C<$result> to be tainted.
=head2 Laundering and Detecting Tainted Data
To test whether a variable contains tainted data, and whose use would
thus trigger an "Insecure dependency" message, you can use the
C function of the Scalar::Util module, available in your
nearby CPAN mirror, and included in Perl starting from the release 5.8.0.
Or you may be able to use the following C function.
sub is_tainted {
return ! eval { eval("#" . substr(join("", @_), 0, 0)); 1 };
}
This function makes use of the fact that the presence of tainted data
anywhere within an expression renders the entire expression tainted. It
would be inefficient for every operator to test every argument for
taintedness. Instead, the slightly more efficient and conservative
approach is used that if any tainted value has been accessed within the
same expression, the whole expression is considered tainted.
But testing for taintedness gets you only so far. Sometimes you have just
to clear your data's taintedness. Values may be untainted by using them
as keys in a hash; otherwise the only way to bypass the tainting
mechanism is by referencing subpatterns from a regular expression match.
Perl presumes that if you reference a substring using $1, $2, etc., that
you knew what you were doing when you wrote the pattern. That means using
a bit of thought--don't just blindly untaint anything, or you defeat the
entire mechanism. It's better to verify that the variable has only good
characters (for certain values of "good") rather than checking whether it
has any bad characters. That's because it's far too easy to miss bad
characters that you never thought of.
Here's a test to make sure that the data contains nothing but "word"
characters (alphabetics, numerics, and underscores), a hyphen, an at sign,
or a dot.
if ($data =~ /^([-\@\w.]+)$/) {
$data = $1; # $data now untainted
} else {
die "Bad data in '$data'"; # log this somewhere
}
This is fairly secure because C\w+/> doesn't normally match shell
metacharacters, nor are dot, dash, or at going to mean something special
to the shell. Use of C would have been insecure in theory because
it lets everything through, but Perl doesn't check for that. The lesson
is that when untainting, you must be exceedingly careful with your patterns.
Laundering data using regular expression is the I mechanism for
untainting dirty data, unless you use the strategy detailed below to fork
a child of lesser privilege.
The example does not untaint C<$data> if C