Sometimes you will want to write a CGI script which interacts with the system. This can result in major security risks if the commands executed on the system are based on user input. Consider the example of a 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`; # backticks used to execute shell command |
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 running perldoc perlsec section of the online documentation, or on page 356 of the Camel.
-T stands for "taint checking". Data input by the user, either via the command line or an HTML form, 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.
The only thing that will clear tainting is referencing substrings from a regexp match. perldoc perlsec contains a simple example of how to do this, about 7 pages down. 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.
The HTML file finger.html asks the user for an account name about which to obtain information {using the Unix system's finger command}. It calls the CGI script cgi-bin/finger.cgi which uses taint checking.
Why is the data input by the user tainted?
Add a -T flag to the shebang line of finger.cgi so that the script performs taint checking
Try re-submitting the form - it should fail
To untaint the data, you need to clean up any unwanted characters. Use some code similar to that in perldoc perlsec to remove anything other than alphanumeric characters and assign the valid part of the user input to a new variable.