PHP Mail Form Email Injection Hijack
{ September 13th, 2005 }
Spam is one thing, but hijacking form mail scripts and spoofing other people’s domains and email is downright wrong. We need tough(er) penalties against these guys.
Lately my customers and I had been receiving hundreds of email sent from the forms on our sites. All form fields were filled out with email addresses from the domain in which it was sent. After checking the headers it was found that most had a BCC address of jrubin3546@aol.com.
After a little research, and a heads up by a fellow website designer in my area, it looks like this automated hijack is going to become a very big and widespread problem.
Hijack Overview
The “attacker” sends an automated bot to exploit unchecked fields in contact forms. It works by assuming a field used in an email header (e.g.: “From:” or “Subject:”) is passed unchecked to the mail subsystem. Appending a newline characters and more header lines with a BCC list and a spam message body might trick the underlying mail system into relaying spam messages. Currently it seems to be just phishing for vulnerable scripts sending emails via Bcc.
Current List of Bcc Recipients (in alphabetical order):
angelrrsmr@aol.com
bergkoch8@aol.com
cameronmtc@aol.com
damnitmayn@aol.com
Homeiragtime@aol.com
Homeragtime@aol.com
jrubin3546@aol.com
jshmng@aol.com
killerhamster@punkass.com
kolyathekid1@aol.com
kshmng@aol.com
kshmng@aol.com
lshmng@aol.com
mhkoch321@aol.com
wnacyiplay@aol.com
wolfione@aol.com
wwjdkid14@aol.com
The Fix?
It seems that stripping fields for carriage return (”\r”) and newline characters (”\n”) used directly in email headers resolves the problem. Note all your Post-Data variables (var) must be protected:
if (eregi (”\r”, $_POST[’var1′].$_POST[’var2′].$_POST[’var3′].$_POST[’etc’])) {die(”SPAM Injection Error :(”);}
if (eregi (”\n”, $_POST[’var1′].$_POST[’var2′].$_POST[’var3′].$_POST[’etc’])) {die(”SPAM Injection Error :(”);}
if (eregi (”Content-Transfer-Encoding”, $_POST[’var1′].$_POST[’var2′].$_POST[’var3′].$_POST[’etc’])) {die(”SPAM Injection Error :(”);}
For even more protection add:
if (eregi (”MIME-Version”, $_POST[’var1′].$_POST[’var2′].$_POST[’var3′].$_POST[’etc’])) {die(”SPAM Injection Error :(”);}
if (eregi (”Content-Type”, $_POST[’var1′].$_POST[’var2′].$_POST[’var3′].$_POST[’etc’])) {die(”SPAM Injection Error :(”);}
More Information
Email Injection
Crack.Attempt to Relay Spam










September 16th, 2005 at 5:20 am
Thanks for this article, it’s proved to be a godsend for my site which has recently come under attack from these mindless email form injections.
Great work!
September 16th, 2005 at 4:11 pm
Great article.
I had to come up with a different way to stop hijacks as we have TEXTAREA fields and would like to keep the formatting of the cr/lf.
$from=replace($_POST[“sender???] , ???:??? , ““);
$message=replace($_POST[“message???] , ???:??? , ““);
etc…
and then we use the variables in the mail function
I know that the recipient of the form would still receive the email – but the hacker would not be able to include any other headers. The added benefit is that you can keep the formatting of the TEXTAREA fields (with the removal of the colons)
And you would also know if someone is trying to hack your form
September 16th, 2005 at 4:37 pm
Raymond, accually you can leave out the TEXTAREA variables in the first two lines of my fix above. The other lines make sure no other headers are included.
September 16th, 2005 at 4:53 pm
One more thing. If you wish to stop all those anoying “Test” emails from being sent try:
//Prevents Test Emails From Being Sent
if (eregi (”@”, $_POST[’Fax’])) {die(”SPAM Injection ErrorPlease Go Back and fill out the form properly.”);}
Note that the “Fax” field was used as it souldn’t contain a “@”.
You could also use a hidden form field.
September 16th, 2005 at 10:35 pm
Today I’ve seen over 100,000 hits with only BergKoch8@aol.com. This means nearly that number of web forms got the probes and published it on their pages. And probably many of them are exploited now as spamrelays too.
The idea with the hidden form field will work with the current version of that spambot, but future version may easily copy the constant content of a hidden field to the POST data the spambot submits to the script. Same is with the incomplete HTTP_REFERER string and the missing HTTP_USER_AGENT the bot sends.
September 19th, 2005 at 6:55 am
How can we do the same using the CDONTS object in asp
September 19th, 2005 at 1:00 pm
hi,
thanks for the suggestions. one of my client websites has been having the same problem — endless ‘test’ emails Bcc:’d to random email addresses, with the same fake email in each form field. I implemented the following check within the ASP code that runs the form mailer:
if ((inStr(Request("fax"),"@")=0) and (inStr(Request("phone"),"@")=0) and (inStr(Request("zip"),"@")=0)) then(business as usual)
else(invoke spambot protection error)
end ifhopefully this will cut down on the number of ‘tests’ that clog up my client’s email inbox (and mine, since I get copied on them all)…
September 20th, 2005 at 6:21 am
This is all new to me - can you clarify whether it is necessary to check ALL form data, or only those fields which are then used in the mail headers? (Typically I only put the sender email address into the email header, and then only after checking the format).
Thanks for your help.
M.
September 20th, 2005 at 9:32 am
Malcolm, all your Post-Data variables must be protected. So what ever form fields you have (even hidden) must be stripped.
September 20th, 2005 at 1:03 pm
Orlando, Florida, September 19th, 2005.
Email Injection TRAP
I am recording who these guys are, from where they
are coming from, they can’t hurt me no more, and if they show up, I
put them to sleep for an hour.
Sounds good, doesn’t it.
I am visited every 5 or 6 days, with the exception of August 31st and
September 1rst.
If someone is touched every day and can implement this script will
be awesome. Post the results. Thank you.
I am assuming..,
As Barbara from UK posted:
Barbara from UK
#275 | Wed, Sep 14, 2005 08:37 AM
http://www.anders.com/cms/75/Crack.Attempt/Spam.Relay
That the spam-bot has the url address of my cgi script form handlers
and is injecting whatever he/she want exploiting the poor cgi programming
made. (For other will be PHP, or ASP, who knows)
THESE IS NOT A DEFINITIVE SOLUTIONS, IT IS JUST A WAY TO FIGHT BACK
WHEN THEY SHOWS UP. BETTER FORM HANDLERS IS WHAT WE NEED.
Here is what I made.
Hello, like many others on the internet I was hit
by these guys that deserve being in jail big time.
here are the records I have of total visits.
bergkoch8@aol.com Wed, 31 Aug 2005 21:06:24 -0400
Form processed at Wed Aug 31 21:06:24 EDT 2005
From IP: 146.83.216.207
TOTAL 45 EMAIL SPAM RECEIVED
jrubin3546@aol.com Thu, 1 Sep 2005 19:16:03 -0400
Form processed at Thu Sep 1 19:16:03 EDT 2005
From IP: 194.117.20.30
TOTAL 47 EMAIL SPAM RECEIVED
jrubin3546@aol.com Tue, 6 Sep 2005 06:54:54 -0400
Form processed at Tue Sep 6 06:54:54 EDT 2005
From IP: 82.67.11.110
TOTAL 48 EMAIL SPAM RECEIVED
jrubin3456@aol.com Mon, 12 Sep 2005 04:28:11 -0400
Form processed at Mon Sep 12 04:28:11 EDT 2005
From IP: 216.194.16.226
TOTAL 94 EMAIL SPAM RECEIVED
Homeiragtime@aol.com Sat, 17 Sep 2005 19:27:05
-0400
Form processed at Sat Sep 17 19:27:04 EDT 2005
From IP: 170.148.96.108
TOTAL 45 EMAIL SPAM RECEIVED
I discovered that about 8 cgi script in my site are
potentially evolved in the risk of been hijacked and
used as source of spam. Really they are very poor in
programming security. (Usually called on the “action” field
in a form)
Beside these I have more script that must be fixed
ASAP.
example:
http://www.mywebsite.com/cgi-bin/script-1.cgi
http://www.mywebsite.com/cgi-bin/script-2.cgi
http://www.mywebsite.com/cgi-bin/script-3.cgi
http://www.mywebsite.com/cgi-bin/script-4.cgi
http://www.mywebsite.com/cgi-bin/script-5.cgi
http://www.mywebsite.com/cgi-bin/script-6.cgi
http://www.mywebsite.com/cgi-bin/script-7.cgi
http://www.mywebsite.com/cgi-bin/script-8.cgi
First thing I made was change script’s names and, of
Course, I changed also the call’s name from my html forms.
Then I Used the Mod_Rewrite Apache Directive to
redirect whoever is looking for my scripts names
(the old names) to a script that will log visitors
http environment) information and put them to sleep for
an hour or so.
Please if you don’t understand what it’s going on
here, call somebody who does.
[File created]
.htaccess (Write this file in Pure ascii, notepad is ok)
RewriteEngine on
Options +FollowSymlinks
RewriteBase /
RewriteRule ^\old-script-1.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
RewriteRule ^\old-script-2.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
RewriteRule ^\old-script-3.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
RewriteRule ^\old-script-4.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
RewriteRule ^\old-script-5.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
RewriteRule ^\old-script-6.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
RewriteRule ^\old-script-7.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
RewriteRule ^\old-script-8.cgi$ /cgi-bin/death-meat.cgi?%{REQUEST_URI}
As you can see all the requests are re-directed
(Internally, trough Apache system)
to a script called death-meat.cgi (sample name, you can use anything you want)
##############################################################################
# NOTE, DO THIS AT YOUR RISK:
# Upload the file to your cgi-bin directory, Please be careful, don’t
# make any mistake, check with your web master or ISP before uploading
# this file, if you are already using .htaccess file, just add the above lines.
# do it wrong and your site will disappear from the web until your ISP delete
# or replace the .htaccess file. (I know it for my own past experience).
##############################################################################
The following script is not my creation, I just
modified one I am using for other purposes.
Those who have access to the features below will be
able to help in the capture of these bastards or at least make
their brilliant ideas more difficult to implement.
My site is stored under Linux OS, Apache webserver.
I have access to cgi scripts, I can write the
.htaccess file and upload it.
and obviously I can run CGI scripts.
Upload the file below to your cgi-bin directory in
ascii (text) only Use a simple text editor, notepad is fine, after
uploaded change chdmod 755
Create a folder inside cgi-bin, stats >chdmod 777,
and inside stats the file igotyou.log (I don’t know if
it will be created
automatically)
[death-meat.cgi file name]
#!/usr/bin/perl
# If required, adjust line above to point to Perl 5.
######################################################
# THIS IS WHAT IS GOING TO HAPPEND,
# AFTER THIS SCRIPT COLLECT SOME VISITOR’S INFORMATION
# WHICH IT MAY BE USEFULL OR NOT, DEPENDING IF THEY DO NOT
# MAKE ANY MISTAKE AND ALLWAYS SEND THE BOT TROUGH A ANONIMUS PROXY
# OTHERWISE WE GOT THE REAL PHISICAL ADDRESS.
# THE SCRIPT WILL PUT THE VISITOR TO SLEEP FOR ABOUT AN HOUR
#
$stats_dir = “stats”;
$log_file = “igotyou.log”;
$sleeptime = 3600;
$remote_host = “$ENV{’REMOTE_HOST’}”;
$remote_addr = “$ENV{’REMOTE_ADDR’}”;
$user_agent = “$ENV{’HTTP_USER_AGENT’}”;
$referer = “$ENV{’HTTP_REFERER’}”;
$document_name = “$ENV{’QUERY_STRING’}”;
&get_date;
&log_hits
(”$date $remote_host $remote_addr $user_agent $referer
$document_name\n”);
print “Content-type: text/plain\n\n”;
print @TEXT;
######## THE SPIDER-BOT OR THE BROWSER GET TRAPPED HERE FOR AN HOUR
sleep ($sleeptime);
######## WAITING…, WAITING…,WAITING….
exit;
sub get_date {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime();
$mon++;
$sec = sprintf (”%02d”, $sec);
$min = sprintf (”%02d”, $min);
$hour = sprintf (”%02d”, $hour);
$mday = sprintf (”%02d”, $mday);
$mon = sprintf (”%02d”, $mon);
$year = scalar localtime;
$year =~ s/.*?(\d{4})/$1/;
$date=”$year-$mon-$mday, $hour:$min:$sec”;
}
sub log_hits {
open (HITS, “>>$stats_dir/$log_file”);
print HITS @_;
close (HITS);
}
############################################
I am testing the urls trying to reach the cgi script
and it work perfectly.
I hope somebody else can try it and post the results.
Good Luck,
Hector Gonzalo
hector2561@yahoo.com
September 20th, 2005 at 3:26 pm
Help! I really don’t understand a lot about PHP, but our site’s “request for information” form has been getting hit by the mhkock321 address, and it is really frustrating. The code for the PHP mail sender is below. What do I need to add or change? Any help would be soooooo appreciated!
“,
“Contact Email from _____.com”,
“Name: $_REQUEST[name]\n”.
“Email: $_REQUEST[email]\n”.
“Industry Type: $_REQUEST[industry]\n”.
“Topic of Interest: $_REQUEST[interest]\n”,
“From: Our Web Site”
);
header(”Location: http://www._____.com/newsletter_thanks.php“);
?>
September 20th, 2005 at 10:32 pm
Thanks for all the great posts and the links to the other discussions regarding injection hacks.
September 21st, 2005 at 8:43 am
Hello,
PHP users may refer to this article where it is all documented.
See http://securephp.damonkohler.com/index.php/Email_Injection
Actually, the article was inspired from an older one (in French) referenced at bottom of page.
hih,
JJS.
September 22nd, 2005 at 6:28 pm
These are a couple of functions that I am trying to break the injection hacks.
sanitize_textarea() lets me use textarea input objects but will kill the process if there are cc, bcc, Content-Type or Mime headers/text in the input. I selected these headers because they seem to be the most useful to the injection hacks.
These are not 100% but are much more selective than just stripping the \r and \n characters.
function sanitize($varg) // This function attempts to break injection hacks.
{
$varg=stripslashes($varg);
$carturn=’\r’;
$newline=’\n’;
// echo(”$varg”); // This line for testing purposes only.
if (eregi($carturn,$varg) || eregi($newline,$varg))
{
// exit(”Failed on $varg.”);
exit(”Form data syntax failure.”);
}
}
function sanitize_textarea($varg) // This function attempts to break injection hacks in textarea input objects.
{
$varg=stripslashes($varg);
$cont=”content-type”;
$cc=”cc”;
$bcc=”bcc”;
$mime=”mime”;
$newline=’\n’;
// echo(”Message $varg”); // This line for testing purposes only.
if (eregi($cont,$varg) || eregi($cc,$varg) || eregi($bcc,$varg) || eregi($mime,$varg))
{
// exit(”Failed on $varg.”);
exit(”Form submission syntax failure.”);
}
}
September 23rd, 2005 at 6:44 am
Great article, I have the same problem and now I have also the solution. In the BBC Recipient list I found:
bergkoch8@aol.com
Homeragtime@aol.com
Thank you!
September 23rd, 2005 at 10:25 am
Hi, I am desperately trying to solve my problem with this. I am getting a bunch of these. I currently have a very standard form that submits to the following .ASP page which formats and send the email. Can anyone suggeest the solution according to what I am trying to accomplish here? Thanks in advance!
——-
September 23rd, 2005 at 10:29 am
i posted a text file version of the code at the following URL:
http://www.jwhowarddesign.com/samplecode.txt
November 16th, 2005 at 10:21 am
I have been tweaking my filters a bit. Its still just an attempt at sanitizing input but seems to have have helped tremendously.
function sanitize($varg) // This function attempts to break injection hacks.
{
$varg=stripslashes($varg);
if (!(strpos($varg,’\r’)===false) || !(strpos($varg,’\n’)===false) || !(strpos($varg,’0×0D’)===false) || !(strpos($varg,’%0D’)===false))
{
exit(”Form data syntax failure. Error 2.”);
}
}
Of course you can add whatever search strings you need. Simple and effective from what I have seen.