Perl Security Tips

Database Access | File Access

Many security documents are already available for Perl, including the perlsec documentation and the security chapter in Programming Perl. This page details various security tips and tricks for Perl.

Database Access

Databases may allow untrusted input to run. Solutions include taint checking all user input for problems, and using placeholders to avoid Structured Query Language (SQL) injection attacks. See the DBI Perl module documentation for additional pointers.

When using a transactional database, wrap read-only SELECT statements in a transaction, then rollback the transaction when done. Using this trick, even if an attacker inserts a malicious SQL statement, their changes will be undone when the transaction rolls back. The example code below uses the DBIx::Simple wrapper for DBI.

use DBIx::Simple ();

my $db = DBIx::Simple->connect("dbi:Pg:dbname=data");



sub select {
$db->begin_work;
my $data = $db->query(qq{SELECT * FROM test WHERE foo = $bar});
$db->rollback;


}

File Access

When opening a filename stored in a variable, unexpected behavior may result due to how the open function parses that variable. The following code should print the contents of a file, though can be tricked into running and showing the output of arbitrary commands, as the second example shows:

$ perl -we '$f = shift; open F, "$f"; print while <F>' /etc/passwd

$ perl -we '$f = shift; open F, "$f"; print while <F>' 'ls /etc|'

To avoid this problem, always specify the redirection statement such as > before the variable, and include a space between the redirection statement and the variable containing the filename:

$ perl -we '$f = shift; open F, "< $f"; print while <F>' /etc/passwd

$ perl -we '$f = shift; open F, "< $f"; print while <F>' 'ls /etc/|'
readline() on closed filehandle F at -e line 1.

Modern versions of Perl have improved the open function. If code will only run on newer versions of Perl (5.8 and above), always use the three-argument method:

open(my $fh, '<', $file) or die "error opening $file: $!\n";