T
TDuncklee
Guest
PHP Email Injection. If your users have php email forms you are an open relay!
Ive managed to stop the hackers/spammers from using php email injection on my customers forms. http://securephp.damonkohler.com/index.php/Email_Injection
The correct way to stop this hack is for all form data to be properly validated. However, even just explaining what the issues are to some customers is impossible so I had to come up with a server wide solution. I also log all form submissions for now. Ill look through them occasionally to see if a spammer got through somehow. At the end of the code are the things I check for to flag it as spam. This is a tough one but for now it seems every message Ive looked at has multiple Subject: s so if I find that I drop the message. I also am checking for the known test email addresses the spammers are using. PLEASE, if anyone has ideas on what to look for to definitively determine if it is an email injection spam message, post them. Also, they do not change their test addressees very often in the thousands of messages Ive looked at anyway. If anyone sees a new address, post it.
Here is what I did:
Create a php script called fake_sendmail.php
Create /usr/mailarchive_php/ and make it rwx by apache only. This is where I chose to log messages for now.
In /usr/local/psa/apache/conf/php.ini add
sendmail_path = /path/to/fake_sendmail.php -t -i
Restart apache
Ive managed to stop the hackers/spammers from using php email injection on my customers forms. http://securephp.damonkohler.com/index.php/Email_Injection
The correct way to stop this hack is for all form data to be properly validated. However, even just explaining what the issues are to some customers is impossible so I had to come up with a server wide solution. I also log all form submissions for now. Ill look through them occasionally to see if a spammer got through somehow. At the end of the code are the things I check for to flag it as spam. This is a tough one but for now it seems every message Ive looked at has multiple Subject: s so if I find that I drop the message. I also am checking for the known test email addresses the spammers are using. PLEASE, if anyone has ideas on what to look for to definitively determine if it is an email injection spam message, post them. Also, they do not change their test addressees very often in the thousands of messages Ive looked at anyway. If anyone sees a new address, post it.
Here is what I did:
Create a php script called fake_sendmail.php
Code:
#!/usr/local/psa/apache/bin/php
<?php
// script to filter email generated from php mail() function.
// Used to block spammers from abusing the function as described here:
// [url]http://securephp.damonkohler.com/index.php/Email_Injection[/url]
// modify php.ini
// sendmail_path = /path/to/fake_sendmail.php -t -i
// If message does not pass the message_chk function we just
// drop the message on the floor.
$size_of_mbox = 10; // Approx max size (in Meg) of logged messages
$sendmail="/usr/local/psa/qmail/bin/sendmail"; // the real sendmail program
$args = "";
for( $i=1; $i <= $argc; $i++ ){
$args .= $argv[$i]." ";
}
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
$email .= fread($fd, 1024);
}
fclose($fd);
$lines = explode("\n", $email);
$from = "";
$subject = "";
$headers = "";
$message = "";
$splittingheaders = true;
for ($i=0; $i<count($lines); $i++) {
if ($splittingheaders) { // this is a header until we find empty line
if (trim($lines[$i])!="") {
$headers .= $lines[$i]."\n";
} // look out for special headers
if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) {
$subject = $matches[1];
}
if (preg_match("/^From: (.*)/", $lines[$i], $matches)) {
$from = $matches[1];
}
} else { // not a header, but message
$message .= $lines[$i]."\n";
}
if (trim($lines[$i])=="") { // empty line, header section has ended
$splittingheaders = false;
}
}
$chk_result = message_chk( $headers, $message );
if( file_exists( "/usr/mailarchive_php/php_mail_log" ) ){
if( (filesize( "/usr/mailarchive_php/php_mail_log" )/1024/1000) > $size_of_mbox ){
rename( "/usr/mailarchive_php/php_mail_log",
"/usr/mailarchive_php/php_mail_log.".date( "y_m_d_H_i_s" ) );
}
}
$archive_fp = fopen ("/usr/mailarchive_php/php_mail_log", "a");
fwrite( $archive_fp, "*******\n" );
if( $chk_result ){
fwrite( $archive_fp, "******* Block Rule: ".$chk_result . "\n");
}
fwrite( $archive_fp, "Custom-Info2: Sent with php\n\n" . $headers.$message );
fclose( $archive_fp );
if( !$chk_result ){
$fps = popen( $sendmail . " " . $args, "w" );
// Doing this so I can identify all PHP created messages.
fwrite( $fps, $headers . "Custom-Info2: Sent with php\n\n" . $message );
pclose( $fps );
}
function message_chk( $headers, $message ){
if( substr_count ( $headers, "Subject: " ) > 1 ){ return "Multiple Subject:'s"; }
else if (eregi( "[email protected]", $message.$headers ) )
{ return "[email protected]"; }
else if (eregi( "[email protected]", $to.$subject.$message.$headers ) )
{ return "[email protected]"; }
else if (eregi( "[email protected]", $to.$subject.$message.$headers ) )
{ return "[email protected]"; }
else if (eregi( "[email protected]", $to.$subject.$message.$headers ) )
{ return "[email protected]"; }
else if (eregi( "[email protected]", $to.$subject.$message.$headers ) )
{ return "[email protected]"; }
else if (eregi( "[email protected]", $to.$subject.$message.$headers ) )
{ return "[email protected]"; }
else if (eregi( "[email protected]", $to.$subject.$message.$headers ) )
{ return "[email protected]"; }
}
?>
In /usr/local/psa/apache/conf/php.ini add
sendmail_path = /path/to/fake_sendmail.php -t -i
Restart apache