Many of the examples given above can result in major security risks if the commands executed are based on user input. Consider the example of a simple finger program which asked the user who they wanted to finger:
#!/usr/bin/perl -w use strict; print "Who do you want to finger? "; my $username = <STDIN>; print `finger $username`; |
Imagine if the user's input had been skud; cat /etc/passwd, or worse yet, skud; rm -rf /. The system would perform both commands as though they had been entered into the shell one after the other.
Luckily, Perl's -T flag can be used to check for unsafe user inputs.
#!/usr/bin/perl -wT |
Documentation for this can be found by reading the perldoc perlsec, or on page 356 of the Camel.
-T stands for "taint checking". Data input by the user is considered "tainted" and until it has been modified by the script, may not be used to perform shell commands or system interactions of any kind. This includes system interactions such as open(), chmod(), and any other built-in Perl function which interacts with the operating system.
The only thing that will clear tainting is referencing substrings from a regexp match. The perlsec online documentation contains a simple example of how to do this. Read it now, and use it to complete the following exercises.
Note that you'll also have to explicitly set $ENV{'PATH'} to something safe (like /bin) as well.
Modify the finger program above to perform taint checking (Answer: exercises/answers/taintfinger.pl)
Take one of your scripts using open() or opendir() and modify it to accept a filename as user input. Turn taint checking on. What sort of regular expression could you use to check for valid filenames? (Answer: exercises/answers/taintfile.pl)