CGI: Safety First

A practical guide to safe CGI.
Good Things

It's time for something less depressing. Can you do it right? Sure you can—it just takes a little bit of effort. The problem is you don't really want your CGI scripts to be executed by a stranger like www. You want to have your scripts running as yourself! For the execution of programs as another user, suid and sguid were invented.

If you make a program suid (or sgid), you run it as the user (or group) who owns the file. That was exactly what you wanted in the first place. So you make your scripts suid. And still under Linux it doesn't work. Why? Because suid scripts are insecure and the Linux kernel refuses suid scripts altogether (look at the comp.os.unix FAQ for some stunning ways to become root).

But suid programs are safe to use. It only means that you have to write a wrapper, a little C program, counter.c, which you make suid:

#include <stdlib.h>
void main(int argc, char *argv[])

Does this suid stuff always work? No—many system administrators mount /home as nosuid, meaning the suid bit will never be honored. Why does a system administrator want to do that? Well, you noted the first script in the article that made a suid shell? That wouldn't have worked if /tmp was mounted nosuid. Many system administrators mount only those file systems as suid which must contain suid programs, mounting all others nosuid; for instance, /home doesn't need suid programs for the system to run, so mounting nosuid is a pre-cautious action.

But there is another way. It's a bit like shotgun programming, but you can let sendmail and procmail do the dirty work for you. How does it work? Basically you let the daemon send you mail that will instruct you to perform a certain task. The receiving sendmail will look in your ~/.forward and see that you want your mail to be processed by procmail, which will perform the update script for you. Let me first give you the CGI script:

cat <<EOF
Content-type: text/plain
You are number $ACCESS to visit this page!
echo "Subject: 1928397071" | sendmail foo

First some remarks about the mail:

  • This mail has no body, which is allowed by RFC 822 (the Internet standard describing the format of mail messages). If you want to include a body, you should precede the body by a mandatory empty line.

  • In the subject we have a script part that will hint at what script to run. It has some sort of a magic cookie (1928397071) to prevent you from processing e-mail which is accidently triggered. If you want this to be a really secure cookie, you shouldn't be writing this line as a script.

Next it is time for the ~/.forward:

"|IFS=' '&&exec /usr/bin/procmail -f-||exit 75 #bar"

The program procmail needs to look in your file ~/.procmailrc (which shouldn't be world readable, if you want to use cookies for security):

:0 b
* ^From www
* ^Subject: 1928397071

So if the daemon sends a mail with a subject 1928397071, procmail will run for you:

rm /home/foo/www/access
echo $ACCESS > /home/foo/www/access

Mission accomplished: we have written something safely into a file. Are there any catches? Yeah, sure.

First of all, you need to assure that when two people try to access your page, they won't screw up your files. You need some sort of file locking mechanism (check out flock, which also is available in Perl).

Secondly, the sendmail in the CGI script is nonblocking: it doesn't wait until the update is actually done. In most cases, this doesn't really matter, as you are only doing a simple update. Otherwise, you can always try to implement the Perl client-server model.

Don't go for the easy insecure option; keep it safe. Your system administrator will appreciate it.

Hans de Vreught ( is a computer science researcher at Delft University of Technology. He has been using Unix since 1982 (Linux since 0.99.13) and is a profound MS hater (all their products are Bad Things). He likes non-virtual Belgian beer, and he is a real globe-trotter (already twice round the world).


White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState