Today we will consider web server security and CGI attacks. Any internet server is subject to attacks and exploitable bugs, but most servers that reach wide use are carefully written by experts, and are mature (i.e. relatively carefully checked and debugged) by the time they are deployed on a wide scale. The basic problem is that every CGI script is essentially a miniature internet server, accessible by anyone, and new CGI scripts are written every day by novice programmers with no idea of what they are doing. The "CGI in Perl for Dummies in 24 Hours" crowd, and even many experienced Perl programmers who are not security oriented, may write CGI code with exploitable bugs. Some of the ideas here come from Phrack magazine, Vol. 9 Issue 55.
CGI scripts may be exploited to obtain information about the system that will help hackers break in. Hackers often want to get a regular user login account in order to rifle through directories or look at world-readable /etc files in order to see how they might try to get root access, and a CGI script with exploitable bugs may let them acquire the same information without a user login.
A second and more dangerous kind of CGI bug occurs in CGI programs that process forms input. Forms are useful and can be done safely, but some CGI programs use forms input unsafely and can be tricked into executing other programs (specified by the hacker) while processing forms input. Executing other programs might not seem dangerous if the CGI program is executing with "nobody" permissions, but on many or most systems, this is a critical security breach with which the wily hacker might:
If you are writing CGI scripts in C, this is not an issue, but if you are writing them in Perl, it can be. If the Perl code itself is then responsible for some of the security checks, it can be fooled. Consider code fragments such as
if ("root\0I am invisible" ne "root") # ... do stuff
or
$file="/etc/passwd\0and stuff"
die("no opening /etc/passwd!") if ($file eq "/etc/passwd");
if (-e $file) {
open(FILE, ">$file");
}
In either case, Perl operators such as ne or eq consider the strings
to be allowable, but the underlying C functions will take those strings
to access precisely the names the Perl code is trying to disallow.
There are a couple of morals here. The one from Phrack magazine is: check your string data for bogus characters like NUL bytes. My addition to this is: don't run CGI's with any sort of root access privileges, and keep your regular system configuration files invulnerable to attacks from regular users. CGI's may be run by people without a valid user account on your system, so they should have even less access than regular users, if anything. The problem is that CGI scripts, in order to be cool and powerful, may need to run many programs and combine them in interesting ways in order to produce their normal intended output. Both the CGI programmer and the CGI administrator have to be very careful to provide functionality without compromising security.
Of course, these different exploits can be used in combination. Suppose you are protecting your code from and users running programs by using
if (!(-e $filename)) exit;Well, a user can use a poison NUL byte, as in
$filename="/bin/ls\0|"
Also in Perl, open() defaults to reading, but the initial characters of the string filename given can supply another mode, such as writing. This means if you default your call to open() in a CGI script, as in
open(FILE, $filename)You think they are reading but a wily hacker can be writing, by beginning his filename with a > character. If you explicitly specify your mode as in
open(FILE, "<$filename")you save yourself a lot of grief. Perl is NOT the only or best CGI scripting language and other very high level scripting languages may not have all these vulnerabilities. Do people actually write code with these kinds of vulnerabilities? Yes. Whether they are exploitable depends on the rest of the system security.
Do not use a CGI script in the public domain, since hackers have its source code, without studying its code carefully to ascertain its safety. If other organizations more paranoid than you are using it, it might be more likely to be secure, but don't count on it.
Be especially leery of scripts that read or write files on the host system. It is possibly to exploit a script that is calling a SQL database to read and write records, but it is much easier to exploit a script that is calling open() to read and write files.
Check your input values VIGILANTLY. Abnormal user input is how the hacker tricks your program into doing something unintended. If your program checks every input carefully, it will in general do what you intended to do, and/or detect attempts to subvert it.