::Avoid server side shell scripts like the plague.
As we have said, CGI scripts are the best entrypoint for a potential cracker. This is because most CGI scripts are quick hacks produced by persons not familier with the security implications involved.
There are numerous ways to attack a CGI script: you could attempt to exploit some buffer-overflow, use the script to destroy data (perhaps the script is a front-end to a database), or simply try to insert tainted information into the script causing it to perform functions on the underlying filesystem that the administrator might not want. Because of these things, there are few fundamental design principles that should be kept in mind when researching a particular script:
Can the script run via an alternative interface? I.e., if it uses a database behind the scenes, can it instead interface with another non-CGI application that deals with the database? This can also mean whether or not the CGI can be run securely at certain intervals from a crob-job to generate static pages that are actually read by Apache.
How does the language or the script deal with tainted data? If the script accepts some sort of user definable query (for example, you can search on Google using http://www.google.com/search?q=bugs) can the CGI deal with queries that could compromise the system (for example, http://www.google.com/search?q=bugs%20;%20rm%20-rf%20/*). (For other encodings, see this [page]. Also the specific UNIX shell characters that can cause troubles are &;'`\"|*?~<>[]{}$\n\r)
Are there any inherent security pros or cons with the script's language? Java is known to employ many security layers, PHP is not. ASP, when run on a Windows machine will be very close to the OS kernel, and will run in protected userspace when run under Linux (using something like Mono).
Does the script require to be run with set-UID or set-GID of any priviledged user? If so, ditch it. It's just an open invitation for problems.
Language Security
There are many different languages to use when making a CGI application. Which means, there are many different levels of security and prevention which may or can be done. As a system administrator, you are unfortunately expected to do the impossible: understand and know the strengths and weaknesses of each.
We will not cover all CGI languages available to Linux here, but we will cover some of the most common.
C/C++
Traditionally, CGI applications for UNIX systems were written in C. This should come as no surprise considering that UNIX and C are from the same origins. However, once Perl entered the scene, C-based CGI began to go the way of the dinosaur. C-based CGI can still outperform any other CGI, but it has all of the inherent problems that other C programs have:
Hard to maintain
No garbage collection
No inherent data security or prevention of tainting
Perl
Perl is, by far, the most popular CGI language in use today (although it is being challenged by PHP). Chances are, if you run CGI on your site, you will encounter a Perl script or two.
Perl has some good internal security features that deal with data tainting and has built-in garbage collection, so it can produce very secure CGIs. The problem is that in order to use the anti-data tainting, you have to disable much of Perl's easy to use functionality and it becomes a difficult to use language. The result is that most Perl CGI scripts are insecure in-spite of the fact that Perl can be so secure.
When evaluating a Perl CGI for use on your system, be sure to check that anti-data tainting techniques are employed by checking for "-T" option when invoking Perl at the start of the script:
#!/usr/local/bin/perl -T
PHP
PHP has become a very popular server side scripting language in the last several years. The reason for this is because it is embedded into HTML pages and can be so simple to pick up to a new programmer.
Unfortunately, PHP has a very bad track record for security. There have been many exploits in the PHP modules in use under Apache, it's too easy to create insecure pages and too hard to create secure ones, and data tainting is a non-trivial thing to really impliment.
PHP is also among the most efficient server side scripting languages, which means, if compromised, the attacker can do more damage in less time.
JSP
JSP is Java Servlet Pages, and is (IMHO) the least appreciated of the server side languages. The idea behind JSP is that you embed Java-like code (JSP code is not quite Java, but it is easier to produce) into HTML documents. A pre-processor loads the JSP, compiles it to real Java, which is then compiled to bytecode by a Java compiler. This bytecode is executed from then on whenever the page is called, unless the page source changes.
The end result is a very speedy server side scripting environment that has built in security inheritted from Java (Java has a lot of built in security), and isn't susceptable to various HTML and common CGI attacks because it's precompiled bytecode is not web-accessable (it's stored in a private cache and is ran when needed by Apache).
JSP pages are very easy to make secure. The problem is that very few people actually develop JSP-based CGI applications. So, unless you create your CGI in-house, you will be rather limitted with what you can find.
ASP
There are several good methods for running ASP code under UNIX. One popular way is to use Mono (the open-source implementation of .NET) in conjunction with Apache.
If you use Mono with ASP, you can have fairly secure server side scripting that should be on par with JSP as far as performance is concerned.
The one real downside to ASP with Mono is that Mono is still in heavy development, and its underlying specs could easily change and break your ASP scripts. This might mean more of a maintenance headache than the other more "mature" languages.
Python
Python is another under-apreciated server side scripting language. Python, superficially, looks like Perl with typing and structures derived from Fortran. In spite of that strange comparison, it is a very elegent and powerful language.
It provides good garbage collection and prevents data tainting in an easier to implement fashion than in Perl, but it's structure tends to turn off developers making it hard to find good CGI applications for it.
Shell Scripts
There are some server side scripts that simply use shell scripting to produce their content. These are perhaps the least secure of all the scripts to use because none of the UNIX shells provide the necessary security features you want in a CGI. There is a sort of garbage collection, but there will be no protection against data tainting.
Additionally, the problems associated with data tainting are amplified by the fact that the scripts are already running from a shell (usually, you use data tainting to try and get a script to activate a shell. With shell scripts, you are already in a shell!)