Code Word: Security

Write good code. This should go without saying, but it can't, because bad coding is a consistent problem. People overlook things, neglect tools that would help them avoid security problems, and don't spend enough time considering what they're doing.

Buffer Overruns

The buffer overrun problem occurs when a particular amount of space has been allocated for user input, but the program doesn't do anything to determine whether more input than expected was given. An attacker who carefully constructs input to a program with this problem can make the computer execute his or her instructions without ever logging into the machine, or even having an account on the machine.

It's awful, but this problem still bites us in the rear end in the year 2000. The dilemma has been well known for more than 30 years, but some developers continue to use vulnerable languages. The popularity of languages like Perl and Java are good signs that we're finally moving in the right direction. (It's worth noting that languages like Lisp have been immune to this problem for about as long as we've been aware of it.)

Evaluating Untrustworthy Data

Another common mistake is taking information from an unauthenticated user and evaluating that data without taking precautions. An example might be unsafely opening a connection to a program like sendmail, passing an email address that the user gave as an argument, which is in turn evaluated by the shell. If the user happens to have given an email address that contains shell escapes and commands, you've just executed commands for someone you don't know. Perl's taint-checking feature is fantastic. Use it!

If you have a piece of Perl code that accepted the user's email address from a form and stored it in the variable $email, one way to mail that user would be to open a pipe to sendmail and include the email address as an option to sendmail.

open (MAIL, "|/usr/lib/sendmail 
     $email") or die ("Cannot open 
     sendmail: $!");

Unfortunately, this is horribly insecure, because to accomplish the pipe to sendmail, a shell evaluates the value of $email. If $email contains a command string, the server will run those commands.

If Perl's taint-checking is enabled (by the use of the -T switch on the shebang line), the program would halt instead of running the dangerous code. The -w switch enables the reporting of "warnings." If these flags indicate problems, don't make the problems "go away" by turning off the options that tell you what's happening—fix the problems.

All of my CGI programs, servlets, setuid programs, and daemons begin this way if they're in Perl:

#!/usr/bin/perl -Tw

Also, look at modules like that will give you additional hints and warnings to keep you from doing things that could prove problematic in the long term.

Data Verification

Be sure you understand the data you have before doing something that can cause a problem. For example, if you have a program that uses two digits to represent the year, do you know that the data your code is using actually has two digits there? All of us remember Web sites that proudly welcomed visitors to the year 19100 when the clock struck midnight.

Build Interfaces

Instead of exposing a wide-open interface to something sensitive, like a database, build an interface for it. If an application on your Web server needs to write to the database, build a back-end interface that the Web server will use and let that interface write the data to the database. Going this route will let you limit the commands that the Web server can execute, such as querying the database. Similar solutions can be had by other means, such as properly setting permissions on tables in the database. Use features like this to limit the damage that a break-in will cause you.

No Silver Bullet

No matter what you do, you'll need to give your architecture and your system considerable thought. Even if you're using a safe language like Perl, if you don't know how to use it properly, you might well find that you're writing programs that do what you expect, but also allow others to do a few things you don't expect. —MC