E-mail Form Vulnerabilities
posted November 18, 2005
We are currently seeing an extremely high volume of successful exploits against
customer PHP and CGI scripts that send e-mails. These exploits are intended to
send out junk e-mail across the Internet.
In many cases, we are able to detect such abuses and prevent the mail from being
sent out. In other cases, though, it is indistinguishable from normal activity.
When we locate a vulnerable script that is actively being attacked, we are
disabling it and notifying the customer.
How The Exploit Typically Works
In almost all cases, the attack works by placing a newline character
(represented by \n in the following example) in the field that asks for the
user's e-mail address. For instance, they might put:
joe@example.com\nCC: victim1@example.com,victim2@example.com
If a script uses that e-mail address as the From header of the resultant e-mail,
and does not carefully check the contents before using it, the script is
likely to create these headers:
To: youraddr@example.com
From: joe@example.com
CC: victim1@example.com,victim2@example.com
And the e-mail is sent to all of the addresses.
This exploit can be done against any form data that is placed in the headers
of an e-mail, be it From, Subject, or another field.
How To Protect Your Site
Our strong recommendation is to use the
formmail.pl
and cgiemail
scripts we provide in our system cgi-bin wherever possible.
cgiemail in
particular is very flexible and can suit most e-mail gateway needs.
Those scripts have been extensively tested and hardened against this and other
types of exploits.
If you need to use a custom PHP or CGI script as an e-mail gateway, please
ensure you are filtering all data received from the form, and remove any
unexpected characters. For instance, these sample code snippets would check
for all the non-printable codes in the standard ASCII set, including null
bytes and newlines, and exit immediately if any are found.
PHP:
if (preg_match("/[\\000-\\037]/",$EMAIL)) { die(); }
Perl:
if ($EMAIL =~ /[\000-\037]/) { die }
In each example, $EMAIL is used to represent a variable that contains form
data.
Such filtering should be done on all variables containing form data that are
used in the headers of the e-mail.