Re: Help Defending against Email Injection Attacks

From: Date: Mon, 06 Feb 2006 16:07:21 +0000
Subject: Re: Help Defending against Email Injection Attacks
References: 1  Groups: php.general 
Request: Send a blank email to php-general+get-229957@lists.php.net to get a copy of this message
Greg Schnippel wrote:
Has anyone developed a really good defense against email injection attacks? I'm waging a prolonged campaign against these luser hordes on a number of non-profit sites I help maintain. I've tried to secure all of the feedback forms using the function below that I cobbled together from various php security sites on the web. I also set it up so that every time a 'successful' attempt is made, it gets logged to a database before it is emailed. The script worked well for 2-3 weeks and I enjoyed watching the spammers bounce off of the firewall. Unfortunately, they finally figured out how to get through last night and sent out hundreds of emails on a couple dozen sites. I quickly took all of the forms down to plug the breach but I can't keep them down indefinitely. Few questions - - Does anyone have a better regex to use to detect email injection attacks? Part of the problem seems to be that they figured out what values I'm searching for and created a new attack that uses character references (ex. &#089; etc) to get through. - The successful attacks that I logged in my database weren't helpful because they had already been converted to HTML. Is there a better way to store _exactly_ what they entered into the field in the database? - Another way to stop these attacks would be to reject any mail field over a specified length. Is there a limit to how long an email address can be? I don't want to set a limit (ex. 50 chars) that excludes - The most foolproof solution I can think of would be to continue logging the successful entries to a database and _not_ send the email. That way even if they get through, no emails get sent. The form would log the feedback and send an email to the admin that a comment is available for viewing. Is it time to abandon using mail() for all user contributed data? Looking forward to the discussion, - schnippy I've been running FormMail.pl.. yeah, not php.. but.. you may want to take a look at what it does to prevent this sort of thing. It requires the form be filled out from the page on the server.. seems like it does some remote address checking and dumps out if too many come in from the same IP. Also, it only allows the recipient to be a valid user on the server. We've been pretty successful with it so far.. <knocking on wood very rapidly>.
The bottom line, you might find some nice routines which you could enable to create some of the same lines of defense within a php script. Best, John Hinton
#----------------------------------------------------------------------- /** * Secures field against email header injection attacks. * * USAGE:
*      secureFeedbackValue($_POST["to"]);
*      mail($_POST["to"], $_POST["subject"], $_POST["message"]);
* * @param $value value to be cleansed of evil */ function secureFeedbackValue( $value ) { # mail adress(ess) for reports... $report_to = "admin@example.com"; # array holding strings to check... $suspicious_str = array (
           "\r",
           "\n",
"bcc", "cc:", "boundary=", "charset", "content-disposition", "content-type", "content-transfer-encoding", "errors-to", "in-reply-to", "message-id", "mime-version", "multipart/mixed", "multipart/alternative", "multipart/related", "reply-to", "x-mailer", "x-sender", "x-uidl" ); // remove added slashes from $value... $value = stripslashes($value); foreach($suspicious_str as $suspect) { # checks if $value contains $suspect... if(eregi($suspect, strtolower($value))) { $ip = (empty($_SERVER['REMOTE_ADDR'])) ? 'empty' : $_SERVER['REMOTE_ADDR']; $rf = (empty($_SERVER['HTTP_REFERER'])) ? 'empty' : $_SERVER['HTTP_REFERER']; $ua = (empty($_SERVER['HTTP_USER_AGENT'])) ? 'empty' : $_SERVER['HTTP_USER_AGENT']; $ru = (empty($_SERVER['REQUEST_URI'])) ? 'empty' : $_SERVER['REQUEST_URI']; $rm = (empty($_SERVER['REQUEST_METHOD'])) ? 'empty' : $_SERVER['REQUEST_METHOD']; if(isset($report_to) && !empty($report_to)) { @mail ( $report_to ,"[ABUSE] mailinjection @ " . $_SERVER['HTTP_HOST'] . " by " . $ip ,"Stopped possible mail-injection @ " . $_SERVER['HTTP_HOST'] .
                               " by " . $ip . " (" . date('d/m/Y
H:i:s') . ")\r\n\r\n" . "*** IP/HOST\r\n" . $ip . "\r\n\r\n" . "*** USER AGENT\r\n" . $ua . "\r\n\r\n" . "*** REFERER\r\n" . $rf . "\r\n\r\n" . "*** REQUEST URI\r\n" . $ru . "\r\n\r\n" . "*** REQUEST METHOD\r\n" . $rm . "\r\n\r\n" . "*** SUSPECT\r\n--\r\n" . $value . "\r\n--" ); } die ('Snakes on the plane.'); } } }


« previous php.general (#229957) next »