Writing Secure Perl Programs
Peter HaworthIOP Publishing Ltd.
O'Reilly Open Source Convention July 22-26, 2002
|
Outline
|
Introduction
Don't trust the user
|
Robustnessopen STDOUT,'> write-protected'; if( $x == 1 ){ do_this(); }elsif( $x == 2 ){ do_that(); } perl -T
|
Tainting$^X @ARGV %ENV <> read() readline() `` qx() etc shmread() msgrcv() getpw*() etc `` qx() system() exec() kill() unlink() mkdir() umask() chmod() etc open() (for writing) NOT print() or write() $1 , $2 , etc are (almost) never taintedmy($untainted) = $tainted =~ /(\d+)/;
|
Child processes%ENV=( PATH => '/bin:/usr/bin' ); %ENV taint checksPATH IFS CDPATH ENV BASH_ENV # Unsafe: $file eq "; rm -rf /" system "prog $file" and die; # Safe system "prog \Q$file\E" and die; # No shell, and less taint checks (for now) system '/bin/prog',$file and die;
|
Child processes - Safe pipesopen my $fh,"| mail $user" or die; print $fh $msg; close $fh or die; open my $fh,"| /bin/mail \Q$user\E" or die; print $fh $msg; close $fh or die; defined(my $pid=open my $fh,'|-') or die; if(!$pid){ exec '/bin/mail',$user; die "Can't exec"; } print $fh $msg; close $fh or die; open my $fh,'|-','/bin/mail',$user or die; print $fh $msg; close $fh or die;
|
Validate all user inputdie "Bad!" if /[;<>&^"']/; # Bad! die "Bad!" unless /\A[\w\s]+\z/; # Good my ($num) = $input =~ /\A(\d+)\z/ or die "Not an integer"; $num >= 0 && $num <= 100 or die "Out of range";
|
Filenames# Unsafe if $filename eq "/etc/passwd\0" open my $fh, '<', "$filename.safe" or die "Invalid filename"; # Safer die "Invalid filename" if $filename =~ /\0/; open my $fh, '<', "$filename.safe" or die "Invalid filename"; # Prevents ../../../../etc/passwd die "Invalid filename" if $filename =~ m#/#; die "Invalid filename" unless $filename =~ /\A\w+\z/;
|
Magic
|
Web applications - HTML forms<input type="hidden" name="password" value="secret"> # Unsafe # fname=stuff&fname=action&fname=delete %config = ( action => 'create', filename => $cgi->param('fname'), ); # Safe $sth->execute( scalar $cgi->param('fname') );
|
Web applications - Cookies# Standard with perl 5.8.0 use Digest::MD5 qw(md5_hex); $cookie_val = $val . md5_hex( md5_hex($val . $secret1) . $secret2 );
|
Safe sequence numbers
|
Dynamic method names
|
References
|