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. Y 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 = "[EMAIL PROTECTED]";

        # 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.');
                }
        }
}


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to