ACCC Home Page ACADEMIC COMPUTING and COMMUNICATIONS CENTER
Accounts / Passwords Email Labs / Classrooms Telecom Software Computing and Network Services Education / Teaching Getting Help
 
Seminar - Perl II
0. Contents 1. Intro 2. Sources 3. References 4. Packages 5. Classes
6. Ties & DBM 7. Typeglobs 8. CGI 9. Security 10. Example  

Security

   
 
     
Be Careful
 

Security means defense against crackers. It also means defense against accidents caused by your program or others.

  • Never trust user input. A browser can send arbitrary input to your script. What you put in your HTML forms or javascript is completely irrelevant.
  • Be extra careful with your script. Multiple copies of your script can execute simultaneously, and at arbitrary times. And they run under your identity, with all of your privileges. Accidents can happen, even if they aren't malicious.
 
     
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:

  • Carefully check and sanitize any user data.
  • Always use the explicit full path of the executable.
  • Don't invoke shell processing. Be sure you know when this happens.

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.

  • Backticks always invoke the shell. Be very careful unless you know exactly what is in the backticks. `/usr/bin/date` is pretty harmless, but `/usr/bin/echo $var` depends a lot on what $var really is.
  • system() invokes the shell if the argument is a single string, but does not invoke the shell for multiple strings. system("/usr/bin/echo $var") is dangerous, depending on $var, but system("/usr/bin/echo", $var) is much safer. If $var has bad data, echo might die, but you are not likely to spawn other rogue programs.
  • exec() is much like system(). With a single argument, it uses the shell, but avoids the shell with multiple arguments.
  • open() normally invokes the shell when opening a pipe. However, there is a subtle way around this.
    open(F, "/usr/bin/echo $var|");              # dangerous
    open(F, "-|") or exec "/usr/bin/echo", $var; # safer
    
    The particular construct of -| means to fork a new process and to connect STDIN of the parent to STDOUT of the child. Since the fork returns 0 to the child, the exec will be executed only by the child. Note particularly the use of the multi-value form of exec. You can use |- if you want the parent to write to STDOUT and the child to read from STDIN.
 
     
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
UIC Home Page Search UIC Pages Contact UIC