| ACADEMIC COMPUTING and COMMUNICATIONS CENTER | ||||||||
| |||||||||||||||||||||
Security | |||||||||||||||||||||
| Be Careful | |||||||||||||||||||||
|
Security means defense against crackers. It also means defense against accidents caused by your program or others.
|
|||||||||||||||||||||
| System Calls | |||||||||||||||||||||
|
Perl has many ways of making system calls, including backticks, calls to open() when the file is actually a pipe, system(), and of course an explicit exec() with or without a fork. Each of these is an invitation to a hacker. System calls can be dangerous, particularly if they can be influenced by user data. And perl has various subtleties that may invoke the shell to compute a path or do other processing before the system call is made. This poses an additional risk. Some advice:
Perl's taint checking can help with the first part about sanitizing data. The basic idea is to check for rogue commands, like " ; rm * " stuck on the end of a string. Be sure you know what commands you are really giving. Giving the full path simply prevents someone from changing the path and then running your script from the command line. Don't be unsure of what command you will really run. Avoid using the shell. The shell does a lot of magic, but this can get you into trouble. Best to just execute the command of interest, and not worry about PATH, or wildcards, or shell metacharacters.
|
|||||||||||||||||||||
| File I/O | |||||||||||||||||||||
|
After you get by a successful open(), file I/O has another pitfall. That is, you never know how many copies of your CGI script are running at the same time. So if you do file I/O, you have to be careful that different processes don't try to write to the same file at the same time. If in any doubt, use flock() or some other file locking mechanism. |
|||||||||||||||||||||
| Race Conditions | |||||||||||||||||||||
|
Be aware that your CGI script shares machine resources with other programs, including other invocations of your CGI script. So, for example, if your script needs to append to a file, it's quite possible that in between opening the file for append, and actually appending, some other process might append on it's own. This is a race condition. Program defensively. In this case, seek to the end of file before appending, even though that should have been automatic in the open. |
|||||||||||||||||||||
| Taint Checking | |||||||||||||||||||||
|
Taint checking is perl's way of reminding you to sanitize user data. When taint checking is turned on (as it is anytime you use perlwrap at UIC), perl will not let user data affect anything outside the program. Unless you sanitize it first. Perl can't force you to do a good job of sanitizing, so yes, you can defeat this mechanism if you want to shoot yourself in the foot. But at least you won't pull the trigger by accident. If you need to use user data outside the program, e.g. you want to write the data to a file or use it as an argument to another command, you must untaint the data first. This means you must match the data against a regular expression, and use then assign the regular expression memory to new variables.
$data =~ /^([\w-]{2,8})$/;
$netid = $1; # untainted
$data =~ /(.*)/;
$netid = $1; # untainted, but dumb idea
The first example shows untainting of a variable that
is supposed to contain a netid. We know that netids
can only contain letters, numbers, or hyphen, and can
only be 8 characters long at max. So the regular expression
carefully constrains this. And why not? If it doesn't
match, you don't have a netid. The second example
blindly untaints. Don't do this. You have been warned.
Advice: Check for what's allowed, rather than what's disallowed. It's hard to come up with a complete list of what's dangerous, but much more robust to check for allowed characters. |
|||||||||||||||||||||
| Authentication | |||||||||||||||||||||
|
If you are using perlwrap, authentication is pretty easy. Perlwrap will run bluestem authentication for you, provided the url includes perlwrap-auth. All you have to do is check the environment for REMOTE_USER. If $ENV{REMOTE_USER} is non-null, then it will hold the authentication netid of the user. At that point, authentication is done, and it's up to your script to make its own authorization decisions. |
|||||||||||||||||||||
| Perl II | Previous: 8. CGI | Next: 10. Example |
| 1999-3-3 BobG |
|