#!/usr/bin/perl -T
use CGI::Carp qw(fatalsToBrowser);
use FindBin qw($Bin);
if ($Bin =~ /^(\/home\/someuser\/somewebsite\/\w{2,4}\/cgi-bin)/) {
$Bin = $1;
}
use lib "$Bin";
use Site::HTML;
use strict;
use warnings;
The \w{2,4} allows for the different subdomains used for development, testing, etc.
A few notes:
- \w can be problematic if you use locale, see perlsec. Better limit that more, e.g. lower-case ASCII letters.
- You could avoid the leaning toothpick syndrome by using different quotes for the match operator:
if ($Bin =~ m!^(/home/someuser/somewebsite/[a-z]{2,4}/cgi-bin/)!)
It's not a security thing per se, it just makes the code more readable.
- Your code lacks any handling for a failed validation. If $Bin does not match, you simply continue and hope that taint mode will kill your script. Make that explicit:
if ($Bin =~ m!^(/home/someuser/somewebsite/[a-z]{2,4}/cgi-bin/)! ) {
$Bin = $1;
} else {
die "Go away, stupid script kiddie!\n";
}
# or maybe:
$Bin =~ m!^(/home/someuser/somewebsite/[a-z]{2,4}/cgi-bin/)! or die "W
+here am I?\n";
$Bin = $1;
- You don't need to quote $Bin in use lib "$Bin".
- You are mixing compile time and runtime. FindBin sets up $FindBin::Bin (and all other exported variables) at compile time. use lib uses $FindBin::Bin at compile time. Way after that, at runtime, you are validating and untainting $FindBin::Bin. That won't work. The easiest way to work around that is to use an expression after use lib, as in Re^2: Calculations before using lib; or Re^6: @INC from $0, that evaluates to the untainted version of $FindBin::Bin.
- As explained in Re^5: Using relative paths with taint mode by ikegami, you should use $FindBin::RealBin instead of $FindBin::Bin.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)