As I mentioned earlier in the class, security is a major concern with CGI programs.  When coded properly, CGI programs can be perfectly secure. However, due to the nature of Perl and web servers in general, it can be easy to introduce large security holes.  It can be educational to run a search in the web site on "cgi" to see the kinds of errors that other developers have made.

The two biggest areas of concern with CGI security are handling user input, and secure configuration of the web server itself.

User Input

When running CGI programs, it is important to not put much trust in the integrity or format of the data that is passed in from the browser.  Here are some examples of how data can be manipulated to trick a CGI application.

Problem: Host based authentication:

A CGI application limits its access to clients within a specific DNS domain.  It does this by parsing the "REMOTE_HOST" environment variable or by doing a reverse lookup on the "REMOTE_ADDR" of the client.  However, a hacker at the other end of the connection controls the DNS server that handles reverse lookups for the IP address range that his browser is running on, and is able to return whatever host name he desires for a given IP address.

Solution: Cross reference host lookups

Rather than just doing a reverse lookup on the IP address, the server application should then do a forward look up of the name that is returned.  The application can then compare the results of the forward and reverse lookups to ensure they match.  Note that address spoofing can still spoil this technique.  If the packet appears to come from a different IP address than it's real source, the forward and reverse lookups will not notice a problem.  In this case, the results of the CGI may not make it back to the hacker, but if the object of the forced request was to make the server perform an action rather than getting information, this may not matter.  In a case such as this, one can't use host authentication securely, you may need a VPN type solution.

Problem: CGI program uses and trusts "hidden" variables on a page.

For convenience a shopping cart application includes the price or quantity of an item as a hidden input field or as a value to an item in a drop down list.  This value is then used to calculate a bill.  However, a malicious user saves off the source HTML, edits the "price" variable,  then loads the modified page in their browser and hits "submit".  The client side program blindly accepts the input values, and calculates an incorrect bill.

Solution: Do not store values such as this in the form.

Information such as prices should not be obtained from user input.  Coders also need to remember that "hidden" data is not really hidden.  It can be viewed simply by displaying page source.  Any data that is actually secretive should either not be sent to the browser, or should be encrypted.

Problem: CGI Program uses Java Script for input validation of variables

In order to improve the user interface, a CGI program uses Java Script to perform input validation on the required user input.  However, malicious user saves the page source, complete with Java Script code.  The user then modifies the JavaScript code to allow some illegal value when it performs input validation, loads the modified page, and hits submit.  The CGI program then trusts the "validated" input that has been corrupted.

Solution: Re-validate user input at the server

Using Java Script to validate user input can be useful, since it allows quicker response to the user in case of errors.  However, it does not relieve the burden of validating input from the server.  Both validations will need to occur.

Problem: User sends shell commands as part of input.

Suppose a program used a sub shell to perform an action such as "grep", or "ping".  In a case such as this, the CGI program may do something like this, the program will end up using the "system" call, back ticks, or an "open" statement to run the command and pass the command input from the end user.  A malicious user might type the IP address for the ping as ";cat /etc/passwd". or " | cat /etc/passwd"  The perl program would then run the command as "ping; cat /etc/passwd".  Instead of just running a ping, the program runs a ping, followed by catting out the password file.  The output of both of these commands would go to the browser for the malicious user to see.

Solution: Be careful with user input.

Avoid sub shells when possible, and strip user input of any characters that could be used to invoke another program if the data were used as arguments to a sub shell.  It isn't always obvious when Perl will invoke a sub shell, but it will do so when you call: I will discuss input cleaning more in a moment.

Web Server configuration

Even if programs are constructed safely, problems in web server configuration can be exploited to make CGI programs misbehave.  Here are some common problems to avoid:


Next Previous Other Issues

Copyright 2001 - Andy Welter