Web Security 101

Previous Table of Contents Next

Web Security 101

Before you put CGI programs on the World Wide Web, you need to know a few things. By putting a CGI program on a web page, you are giving remote users (using web browsers) limited access to your system. Using normal HTML documents, they can retrieve only static documents from your web site. Using CGI programs, however, they're actually able to run programs on your web server.

Knowing how to write safe and secure CGI programs will make you and your web server administrator much happier. Writing such programs is not hard; you just need to follow a few simple precautions.

A Clear Link

When a web browser retrieves a page from your web server, the HTML is sent over a cleartext channel (see Figure 22.6). This means that as the data winds its way through the Internet, it's not encrypted, encoded, or otherwise obscured.

Figure 22.6. Plain text being transmitted to server.

The data that a user puts into a form and submits to your CGI program is transmitted with the same protocol as the initial web page. All the fields of the form are free for anyone to see as they go by (see Figure 22.7).

Figure 22.7. Server responding in plain text.

The problem of data being transmitted in the clear is a real one that you should be concerned with. The Internet is not a secure place, and anyone along the wire between the web browser and the web server can eavesdrop on the information being sent out or in.

Keeping this point in mind, you should never transmit some kinds of data with normal CGI forms:

  • Passwords of any kind

  • Personal information (Social Security numbers, phone numbers)

  • Financial information (account numbers, PINs, credit card numbers)

Keep this rule of thumb in mind: Never send anything on the Internet that you wouldn't put on a postcard. If you need to transmit data that needs to be kept secure, you need to use extraordinary methods to do so: use secure HTTP (https) instead of HTTP, make sure that the servers you're sending the data to are secure, and trust the recipient with your information.

By the Way

"But wait!" you say. "I've seen forms on the Internet asking for all those pieces of information and claiming to be secure." Reasonably secure transactions can be performed over the Web with some additional tools. Secure web transactions are actually performed by encrypting the entire browser/server conversation. This is done by using a secure version of the http protocol called https.

Watching for Insecure Data

Another point to consider in writing secure CGI programs is that you're writing programs that will execute Perl commands based on the input given to you by a web page. The InternetŚand possibly your intranetŚis full of people who are not nice and would take great glee and pride in harming your web server. Also, benign users could accidentally send invalid data to your CGI program.

Consider the HTML form in Listing 22.3 and the CGI program in Listing 22.4.

Listing 22.3. Directory Listing Web Form

1: <form action="/cgi-bin/directory.cgi">

2: <p>What directory to list?

3: <input type==text name==dirname/>

4: <input type=submit name=submit value="Run This"/>

5: </p>

6: </form>

Listing 22.4. An Insecure CGI Program Named directory.cgi

1: #!/usr/bin/perl -w

2: # Do NOT use this CGI program, it's very insecure

3: use strict;

4: use CGI qw(:all);


6: print header('text/plain');

7: my $directory=param('dirname');

8: print `ls -l $directory`;  # Do a directory listing

Listing 22.3 presents the user with a short form to collect a directory name and then passes the name to a CGI program called directory.cgi. In Listing 22.4, the directory.cgi program takes the directory and performs an ls -l on itŚfor DOS/Windows users, this is the equivalent of dirŚgiving the user a directory listing.

A program of this sort allows a remote web surfer to explore your entire directory structure. The CGI program does no validation of what the directory name is, and if the browser wants to explore your sensitive data, it may be able to.

The more important point is that $directory might not contain a directory at all! If the web browser had sent back the value /home; cat /etc/passwd for dirname, the command run by the CGI program would have been as follows:

ls -l /home; cat /etc/passwd

This command would send a copy of the system's password file back to the web browser. In fact, any Unix shell command or MS-DOS command could be run this way, including commands to delete files on your server! If your web server has not been set up properly, this could allow any user on the Internet to take full control of your server remotely.

Perl has a mechanism to help prevent you from doing silly things like this. The -T switch on the #! line enables data tainting. As data is received from external sourcesŚfilehandles, network sockets, the command line, and so onŚit's marked as tainted. Tainted data cannot be used in backticks, system calls (such as opening a file for output), the system command, or other places that might compromise your security.

You also cannot use the open function, system function, or backticks in your Perl program when taint checking is in effect unless you explicitly set your PATH environment variable first.

Listing 22.5 shows a more secure version of this program.

Listing 22.5. A Somewhat More Secure Version of directory.cgi

1: #!/usr/bin/perl -Tw

2: # tainting is enabled!

3: use strict;

4: use CGI qw(:all);


6: print header('text/plain');

7: # Explicitly set the path to something reasonable

8: $ENV{PATH}='/bin:/usr/bin';

9: my $dir=param('dirname');

10: # Only allow directory listings under /home/projects

11: if ($dir=~m{^(/home/projects/[\w/]+)$} ) {

12:     $dir=$1;   # This "untaints" the data, see "perldoc perlsec"

13:     print 'ls -l $dir';

14: }

By the Way

For more information on tainted data, how to untaint data, and Perl programs, see the perlsec manual included with the Perl distribution.

Doing the Impossible

HTML/CGI forms can also be undermined in another way. Consider the HTML in Listing 22.6.

Listing 22.6. A Simple Form

1: <form action="/cgi-bin/doit.cgi">

2: <p>Please type in your favorite color:

3: <input type="text" length="15" name="color"/>

4: <input type= submit value="Submit color"/></p>

5: </form>

In this form, the maximum allowable width of the color field is 15, right? Almost. The HTML specification says that length in a text field will allow at most that many characters. However, the browser could be broken, or a malicious person could put more than 15 characters in that field by simply bypassing your form or creating a new one.

Previous Table of Contents Next
© 2000- NIV