CGI, Perl, Scripts, etc.
Section 07: CGI, Perl, Scripts, etc.
07-1. What is CGI?
CGI stands for Common Gateway Interface. It is a way for users to submit requests and have the server perform some function, typically a function that is native to the operating system, to either send a more "dynamic" response to the user, or to gather information about the user. For example, the user fills out a survey form and mails it in, or requests information on a part number and the server looks up the price from a database before sending the user the HTML page.
07-2. Are there default vulnerabilities?
Yes and no. There are "default" vulnerabilities that exist in several example files, as mentioned in Section 02, but there aren't any real default vulnerabilities for the most part. What you have are default bad programming habits that can be taken advantage of.
The bad habits usually involve not properly parsing user-supplied information. This is why some of the stuff in Section 02 works, I've just stated a few examples there. You could get REAL psychotic about this stuff. Besides just grabbing the passwd file, you could try:
- Get any file that is readable from the UID of httpd
- Kick off several "finds" that eat server CPU
- Spawn a high port and telnet in
If the target site for some stupid reason has put PERL.EXE in say, /cgi-bin/ (I've seen this on some NT servers before),you should buy that book on Perl ;-). You can send entire Perl scripts for PERL.EXE to execute including all of the above mentioned items.
One vulnerability that I haven't mentioned is looking for files in /cgi-bin/ with a ~ on the end. If the administrator was editing change-your-password.pl with a package like emacs in the /cgi-bin/, there might be a change-your-password.pl~ backup file that the editor has created. You may be able to find holes in this code if you can read it, instead of simply guessing.
07-3. How do I spot code with holes?
If you can get ahold of actual Perl code, you can check to see if things are being parsed. Let's say you grab finger.pl~ from the /cgi-bin/ directory the way stated at the end of 07-2. Let's say you see the following line (example is for a Unix server):
#!/usr/local/bin/perl <--- The first line says we're using Perl, duh
.
.
.
print `finger $account_to_finger`;
Okay so we can finger an account. The Web page allows you to type in a user name and finger them to see if they are online. In that example supplying
nobody;echo "toor::0:0::/:/bin/sh">>/etc/passwd
as a user name might yield some interesting results, especially if the httpd is running under root. Why does this work? Because in Perl the command in ` ` is run from a spawned shell.
Now what does code look like that is "safe"? Well, first look for Perl running tainted. This means that Perl will assume all user input is tainted and could spread to other parts of the system. Taint checks are similar to these examples:
#!/usr/local/bin/perl -T <--- Perl v5 invoking taint checks
.
.
.
# untaint the address
$user_to_finger=~/([\w-.]+\@[\w-.]+)/;
$untainted_user = $1;
# path hardcoded
$ENV('path') = '/usr/bin;/usr/local/bin:/bin';
# still paranoid let's hardcode the path to finger
system("/usr/local/bin/finger $untainted_user");
Obviously someone is taking more precautions here.
How about more examples of bad code? Well, here's a common example, a simple text file "database" that can be grepped against to return data:
system("grep $variable database_file"); or
sprintf(tmp, "grep %s database_file", variable); system(tmp);
Now what happens if you supply "0:0 /etc/passwd;id" as the variable? You'd get root or root equivalent lines from /etc/passwd, and you'd see which id the httpd process is running under. Of course if it looks like this, a shell is never invoked (note the -e in quotes):
system("grep", "-e", $variable, "database_file");
If you see this, your failed intrusion attempt will simply end up in a log file somewhere.
07-4. Why are buffers so important?
Let's look at some code first discussed in Section 02. Note the following:
/* code snippet in C, although you can do the same type thing in Perl */
sprintf(buffer, "/usr/lib/sendmail -t %s < %s", foo_address, input_file);
system(buffer);
Now let's assume that somewhere at the start of the code is this statement:
char buffer[60];
What will happen if you overflow that buffer? I guess it would depend on the operating system and whether you were running your httpd daemon as root or nobody.
Well, Mr. Admin, you say that no one looks at your source code except existing personnel? Okay, that's fair, and for the sake of argument we will assume that those contractors you hired and you drove like dogs to finish their code are incorruptible angels ;-), so what about vendor code? What about sample code? What about freeware?
Serious intruders will review the code of common shareware and freeware utilities and look for these types of details. Knowing the OS, it's revision, and that a piece of code whose buffer could be overrun an intruder can simply duplicate the environment as best as possible and then start writing their own code until a crack is found.