homepage Welcome to WebmasterWorld Guest from
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

This 51 message thread spans 2 pages: 51 ( [1] 2 > >     
PHP email form script being abused or spammed
documentation of problems encountered

 2:44 pm on Sep 10, 2005 (gmt 0)

By posting this, I wanted to document or "make known" some of the problems I have been having with my online forms being spammed or abused. This post is long, but I tried to document as much as possible.

I would like any suggestions on how to combat this problem if possible. I realize that if you have found a solution to this problem, you might not want to reveal your solution…but any help would be greatly appreciated.

If you have similar problems, and would like to add to this post, please do so. This way we might be able to aid others in combatting this problem with documentation.



1. Online contact / inquiry forms are being abused or submitted multiple times within a span of about 2-5 seconds. The spammer or bot is filling in all fields, including my hidden fields ( such as IP address grabber and date/time script) with randomly generated email addresses. For example, the emails sent via my forms usually look like this:

IP Address: acvhdhf@domainname.com
Date and Time: acvhdhf@domainname.com
Name: acvhdhf@domainname.com
Phone: acvhdhf@domainname.com

The spammer or bot grabs the domain name from the website where the online contact / inquiry form resides…and…places that domain on the end of the random email address as shown above.

I am using a javascript user-side check to verify that the email addresses match. This is to guard against valid users from mis-typing their email address. This leads me to believe that this spammer is using a browser script, such as a greasemonkey script, to fill in these forms…So they can get past this email validation. Once past the user-side validation, the script is executed many times.

The execution times vary in the range of 2-5 seconds…so this leads me to guess that it is a human executing the script…not a bot programmed to execute at regular intervals.

The mail scripts can be executed anywhere from 5-95 times during spamming sessions…or until their finger gets tired or they feel satisfied.


2. I have checked my server logs, and the spammer or bot uses different IP addresses for different spamming sessions…sometimes they are from US, China, Russia, etc. I have checked the IP's against misuse databases and some are noted as spamming IPs and some aren't. So, I will assume that they are random.


3. The typical traversal through a website is homepage -> page1 -> page2 -> page3 -> page4 -> form page -> form script

Then the form script is executed multiple times from the same randomly generated IP address. The submissions stop, and the spammer or bot moves on to another website stored on my webserver.


4. I have been dealing with this problem for about a year. I have been adding in validations to the script regularly based on suggestions found online. Unfortunately, the spammer or bot seems to be "upstaging" me for each adjustment I make.

A "game" of cat and mouse…with my time being wasted…I am just trying to pay back my student loans for Pete's sake by obtaining new customers.

This "game" started out with the forms being submitted with blank fields, for which I countered with a validator to guard against this…user-side and server side.

Then I added in the cookie and session check. This was circumvented as well.

The validations, I have added, go on and on.


I just wanted to make my problems known so that it might be of some help.

Thanks for your time or any suggestions that you might be able to provide.



 3:32 pm on Sep 10, 2005 (gmt 0)

How about adding a code that has to be typed in? - Generate a random number when the page is created which is diplayed and has to be entered so it has to match when the form is submitted?


 3:33 pm on Sep 10, 2005 (gmt 0)

Welcome to WebmasterWorld Aggie.

Sorry for your troubles.

It sounds like you've tried a lot already so I hesitate to throw things out, but ...

dramstore's idea of using a captcha-style thing sounds like the best bet.

Do you think you could grab the IP and hold it for a period (hour, day, month) in a database and only allow one or two messages from a given IP?

Also, I have no idea whether this would work, but could you use the network functions to lookup the IP and see if it matches the domain name? I think you would filter out a lot of valid messages doing that though, using gethostbyaddr()


 3:48 pm on Sep 10, 2005 (gmt 0)



gives a good list of PHP-specific resources for implementing captcha.


 4:12 pm on Sep 10, 2005 (gmt 0)

Thanks for the speedy replies...

Myself and other former CS Aggies have been trying different solutions to the problem that I stated above.


dramstore and ergophobe ~

1. Tried the Random Number generator and they countered that. This was done in the first week…about a year ago.

I have considered using a Touring Test..aka captcha…but based on experience with the spammers or bots…they should be able to get around this too. Additionally, the captcha raises accessibility issues…I even have trouble seeing the letters.

Might be forced to set the captcha up though….but will have to fix client sites as well (150+)


here's some more resources on captcha:


2. Tried many different methods to grab their IP, but it is cloaked on the server side logs as well as on the client side IP grabber script. The spammer or bot actually fills in the client side IP with a randomly generated email address followed by the domain name where the form resides.

I appreciate your suggestions….all are very helpful.

[edited by: ergophobe at 7:29 pm (utc) on Sep. 10, 2005]
[edit reason] "authoritative" URLs only please - no personal sites [/edit]


 4:26 pm on Sep 10, 2005 (gmt 0)

One more comment / question about the captcha…

Once the spammer or bots make it past the captcha, would it be safe to assume that they could execute the script as many times as they want?

…much like they are doing now. My server logs indicate that they never leave the mail script, they just re-execute many times before moving on to the next website and form.

Of course, this assumes that the abuse is coming from a person or AI bot, who can pass the captcha, then hit the script.

At A&M, I have seen AI programs that are able to make difficult decisions: tell the difference b/w colors, directional changes, navigate 3D scene / terrain obstacles, etc.



 4:32 pm on Sep 10, 2005 (gmt 0)

2. Tried many different methods to grab their IP, but it is cloaked on the server side logs as well as on the client side IP grabber script. The spammer or bot actually fills in the client side IP with a randomly generated email address followed by the domain name where the form resides.

even if it is technically possible to "cloak" an ip-address, the spammer needs to attack your network infrastructure first to do so. since the attack you describe is based from the internet (wan), this should not be possible that easy. if you think, this is the case you should immediatly contact your isp.

in general your webserver needs to get the ip address of any client to answer its requests. that is the same for the spammer. so you can get the spammers "true" ip address by reading out the according variables. check the output of phphinfo(); to gain more info, which is the right variable. should be remote_address or similar.

on the other hand: if only the spammer manipulates the input even of the hidden fields, you can check wether the spammer or someone else submitted the data. so what's the problem? you can filter out the spammer input because it has it's own "fingerprint". shouldn't that be a solution?


 7:39 pm on Sep 10, 2005 (gmt 0)

I now am fairly convinced that this abuse is automated.

Done some close monitoring of my logs vs. remote addresses captured today...did this on the server side...and this abuse seems to be coming from servers everywhere.

Each time the "malware" programs are using a different IP address. Some IPs have been used multiple times at differing time intervals on different websites that are hosted on my webserver.

Since I first posted this topic, the form scripts have been hit about 200 times.

I have notified the owners of the recorded IPs and hopefully they can shed some light on the situation.


 10:27 pm on Sep 10, 2005 (gmt 0)

Here's a fairly accurate description of my problem:

<snipped url which described Form Post Hijacking>

The program exploits webservers by first sending a bogus email address checking the script's code. The bogus email address that shows up in my mail logs is:


Once a vulnerable script is found, they use the script to send out spam.

[edited by: coopster at 3:54 pm (utc) on Sep. 19, 2005]
[edit reason] removed url per TOS [webmasterworld.com] [/edit]


 10:43 pm on Sep 10, 2005 (gmt 0)

In reply to hakre:

Source IP addresses can be spoofed ,, as the bot is only trying to submit , it does not care about any responses (that could go to the wrong ip address, etc) .

Id suggest that you employ some bot detection algorithms (honeypotting , etc) , in your scripts , then add the offending 'credentials' to a black list .. ,, maker two or three sets of critera that need to be conditianally checked , that a bot would have difficulty in doing , ie ..

type the following GREEN numbers in
type the following non GREEn numbers in
type the red numbers in
tye the non purple colours in .

and randomise the questions , so they change each time to say , .

type the yellow numbers in
type the following numbers that arnt red in
type all the numbers in
tye the violet numbers in .

Honeypotting would consist of giving a easy way through the script (that the bot would see before any user) , and then ban the ass's off the things that try to go through the pot .

Thats my 2 dollars worth , SM me , if you need more details .


 11:46 pm on Sep 10, 2005 (gmt 0)

I have seen a bunch of form spam threads lately, so I thought I would share something I have been playing around with -- could probably be wrapped in a couple of functions and help someone out... Haven't tested it too extensively, but maybe it will give someone an idea or two.

Most spoofing is done through the use of X-Forwarded-For headers -- Very easy if you can set you own headers, so I would start there:

(To use with all attempted submissions, remove the forwarding check.)

1. Get some clip art that is easily definable:
EG bird, dog, cat, plane, etc - (or create random word/number pics)

2. On the page that generates the form:

if(preg_match("/^[1-3]$/", $_POST['try_again'])) { $try_again=$_POST['try_again']; } // if try again is a number from 1 to 3 with no other characters, this is correct, set it.

elseif(!isset($try_again) ¦¦ empty($try_again)) { $try_again=1; } // If try again is not set or is empty, set it.

else { echo "There has been an error submitting your request. Please empty your browser cache and try again."; exit; } // if try again did not match the pattern of 1 to 3, but is set and not empty, there is something wrong... stop doing anything.

// if the pre-form has been submitted, let's see what they sent us.
if($_POST['real_person_check'] && preg_match("/^[a-z]{mincharsinwords,maxcharsinwords}$/i", $_POST['real_person_check']) && preg_match("/^[0-9]{1,2}$/",$_POST['pic']) {


$possible_matches="bird dog cat plane blah more stuff"; // should be ordered the same as the pictures
$the_match=explode(" ",$possible_matches);
if(!preg_match("/".$real_person_check."\b/i", $the_match[$pic]) {

unset($real_person_check); $try_again++;
else { unset($_POST['real_person_check']); $try_again++; }

// if they are using a proxy, or spoofing headers through forwarding, and have not entered an answer or answered incorrectly, make them type something in (or type something in again):
if($_SERVER['X-Forwarded-For'] && (!isset($real_person_check) ¦¦ empty($real_person_check))) {

// if they have tried 3 times unsuccessfully, tell them what to do
elseif($try_again>=3) {
$Make_them_type="<h1>Sorry, we are unable to process your request...</h1>";
$Make_them_type.="What they should do if they can't figure out what the picture is and they still need to contact you.";

// show them the picture and apologize for the inconvenience
else {
$Make_them_type.="Sorry, spam blah, blah... type what you see in the following picture.\n";
$Make_them_type.="<img src=\"/yourimages/".$rnd_pic.".gif\">\n";
$Make_them_type.="<form method=\"POST\" action=\"$PHP_SELF\">\n";
$Make_them_type.="Please, enter what the picture is:\n";
$Make_them_type.="<input type=\"test\" name=\"real_person_check\" value=\"".$rnd_pic."\">\n";
$Make_them_type.="<input type=\"hidden\" name=\"try_again\" value=\"".$try_again."\">\n";
$Make_them_type.="<input type=\"hidden\" name=\"pic\" value=\"".$rnd_pic."\">\n";

echo $Make_them_type;

// if they are not using forwarding headers or have successfully completed the first question, show them the real form
else {
the real form

3. On the 'real form' processing page, make sure they have entered information correctly, and are not posting extra variables through GET (assuming POST is used for the form and register globals are on for some reason.)


// alphabetical, helps to associate allowed with real, so it should be easy to find anything out of place
// array keys you will allow to be passed
$allowed_keys=array('email', 'sub', 'mess', 'name', 'last', 'blah', 'stuff');

// expressions corresponding to the key you will allow -- duplicated last sets of expressions, should be adjusted according to goals.

$allowed_expressions=array('/^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,6}$/i', '/^[\w\s]{5,max length of subject}$/', '/^[\w\s]+$/iU', '/^[\w\s]{min,max length of name}$/', '/^[\w\s]{min,max length of last name}$/', '/^[\w\s]{min,max length of blah}$/', '/^[\w\s]{min,max length of stuff}$/');

// sort the POSTed information according to key, so we have an accurate comparison

// make sure there are not obviously any extra values in the POSTed information
if(count($allowed_keys)!==count($check)) { echo "There was an error processing your form. Please go back and try again."; exit; }

foreach($check as $key => $val) {
if($key!=$verify_key[$key_cnt]) { $error="There was an error processing your form. Please go back and try again."; break; }
elseif(!preg_match($allowed_expressions[$key_cnt], $val)) { $error="There was an error processing your form. Please go back and try again."; break; }

if($error) { echo $error; exit; ) }
else {
do the real processing

Anyway, back to work...


Edit: Couple of minor things I missed while typing.


 12:20 am on Sep 11, 2005 (gmt 0)

Thanks justin...will take a look at this week. I am amazed at how many people have been affected by these particular bots.

I tried a couple more suggestions I found on the net...will see if those work first.

The key now is to check my mail logs...and look for the bcc: with aol addresses. I didn't code any bcc variables...so I know this is the bot looking for the hole in my form script. I would assume aol address is sent an email notifying the owner of my vulnerability.

I have already gotten lots of calls from clients today telling me that their inboxes were full...this is a bummer.

Anymore documentation from others would be appreciated.

Going to go watch some football now.


 12:56 am on Sep 11, 2005 (gmt 0)


if($key!=$verify_key[$key_cnt]) { $error="There was an error processing your form. Please go back and try again."; break; }

Should be this:
if($key!=$allowed_key[$key_cnt]) { $error="There was an error processing your form. Please go back and try again."; break; }



 4:18 am on Sep 11, 2005 (gmt 0)

on the track of cloaked ip adresses
Source IP addresses can be spoofed ,, as the bot is only trying to submit , it does not care about any responses (that could go to the wrong ip address, etc) .

if the spammer does not to care about communicating with the server, then you have to make him do it: send a temporary redirect first which is a temporary url only existing within the session and offering the form. if the ip address is really cloaked there will be only some bytes going into nirvana and you won't be spamed any longer. real users will not see the difference because the redirect is handled by their browser automatically.


 4:34 am on Sep 11, 2005 (gmt 0)

I would recommend the first course of action would be to ensure that the only information being entered into your form is exactly the information you intend to be entered. In the script you process the form with, do a server-side check of all the input data and strip it of invalid characters (more accurately, only allow valid ones). This will prevent a user from dumping headers into the outgoing mail. If you're using PHP, something along the lines of:

function isValidEmail($email){
$valid = "/^[a-zA-Z0-9_\+\-\:\@\.]+$/";
if(!preg_match($valid, $email)){
return false;

if(!isValidEmail($email)) die("Invalid headers supplied");

would keep him from using an 'email address' or 'subject' field to insert new lines into the message headers. You should also check the referring page to keep someone from posting to a form processor without using the form you intended them to:

if ($_SERVER['HTTP_REFERER']!= "http://www.yourdomain.com/your_form.php") {
die("Invalid request from: " . $_SERVER['HTTP_REFERER']);

is another good measure to use. I wouldn't rule out the possibility of spoofing server side variables, however, I haven't the foggiest idea how to do it, so i consider it a good countermeasure (if for no other reason, to keep me from exploiting my own scripts).

Finally, you can have whichever script sends your mail strip Cc or Bcc lines before sending. Ultimately, you decide what kind of information gets processed in the end when the scripts reside on your server.

Anyways, best of luck with that ornery varmint.


 12:03 pm on Sep 11, 2005 (gmt 0)

Thanks angrybinary and hakre. All of this advice is very helpful. Will try these this week and report back here.



 1:20 pm on Sep 11, 2005 (gmt 0)

This looks like the smarter PHP minds than mine could use it.
A technical article on Email Enjection:


 3:32 pm on Sep 11, 2005 (gmt 0)

Referring to the above link

I'm only a shade tree coder, and as such will happily learn from those more experienced than I, but the article discusses the many ways even a seemingly hard coded (To:) can still be hijacked.

I don't know if our forms are being targeted in this way, but I do know I'm going to have to secure even the mailings done in php.

On the discussion page for this article

sanitizing the mail function by stripping the new lines out of the headers is discussed. I like simple solutions and may plod my way through incorporating something like this.


 6:18 pm on Sep 11, 2005 (gmt 0)

We had similar problems too, and solved it, by NOT publishing the email in a hidden field in the form, but hardcoding it in a config.inc file, or directly in the script.

The spammer does usually not send the form, they access directly the script page, giving the parameters in the URL. So they have just to know what you use as Email variable.

If you give the email in a hidden field, it's very easy to know what variable is the SentToEmail.

This might do for most forms, as most will have anyway just one email they get all emails to, if not you can choose the email in the script too, according to the subject, or form sent. So all the spam goes to your email(s), and the spammer has no reason to spam.

Worked well for us.

(besides, why not simply use $_POST, and unset($_GET))


 6:57 pm on Sep 11, 2005 (gmt 0)

Hi aggievizzer,

Thanks justin...will take a look at this week.

Hope it helps you out. Here are some thoughts on making it work:

You do not actually need the first two sections -- just been in my head, so I thought I would try them out.

Section 3 loops through all keys posted, and breaks if they do not match the keys you will accept, or if the information contained in those keys does not fit the pattern you specify.

EG if someone injected a $header statement in the POST variables, that would be $_POST['header']; it is not in the accepted list, so the form would not process. If someone tried the email@blah.com:someotheremail@blah2.com that would not fit the pattern specified in the e-mail regex and the form would not process.

The toughest part is getting the regex right, if you need any help with those, let us know...

BTW there should probably be a sort() on the $allowed arrays -- see what happens when you change things while posting?



 7:52 pm on Sep 11, 2005 (gmt 0)

All great suggestions! Thanks.

I hope to have enough suggestions + experience to do a write up. Apparently, this is a widespread problem.


 8:02 pm on Sep 11, 2005 (gmt 0)

Just another observation....

I have set up a "monitoring system" to notify me when the bots hit my form scripts...

Once I make a slight change in the code of one of the scripts, they hit one of my forms about 10-50 times. They do not necessarily hit the form script that I had recently edited.

This usually happens less than 1 minute after I post the new file.


 5:23 pm on Sep 12, 2005 (gmt 0)

Thanks AngryBinary,

I have put both of your suggestions into my pages with forms and looks like the problem is solved now or at least for now

function isValidEmail($email){
$valid = "/^[a-zA-Z0-9_\+\-\:\@\.]+$/";
if(!preg_match($valid, $email)){
return false;

if(!isValidEmail($email)) die("Invalid headers supplied");

if ($_SERVER['HTTP_REFERER']!= "http://www.yourdomain.com/your_form.php") {
die("Invalid request from: " . $_SERVER['HTTP_REFERER']);


 11:09 pm on Sep 12, 2005 (gmt 0)

Timely post... I just got tired of the spambot probing enough to search Google for one of their bcc: email accounts, and found a long but useful thread.

I thought my email forms were locked down, but this opened my eyes to a few additional steps I could (and did) to reduce the annoyance and risk factor.

And, yes, I'm sure some spammers read these forums too but that's no reason to make their job any easier.

[edited by: coopster at 3:55 pm (utc) on Sep. 19, 2005]
[edit reason] removed url per TOS [webmasterworld.com] [/edit]


 11:28 pm on Sep 12, 2005 (gmt 0)

ack...newbie error. That thread was already mentioned, early on in this discussion. Apologies for being late to the party.


 3:50 pm on Sep 13, 2005 (gmt 0)

I'd be careful about relying on the referrer. You might prevent legitimate users from submitting forms if there privacy setting are strict. Programs like Norton Internet Security have a setting that allows the user to browse without reporting the referrer. By default I think NIS allows same site referrers, but the setting is there to disallow it too.



 10:31 pm on Sep 13, 2005 (gmt 0)


Dumb question time... I'm also a shadetree PHP'er...

I assume they're using a search engine to isolate these scripts. Are they searching somehow for the HTML:

<form method="POST" action="mailer.php">?

If so, would it be possible somehow to "encode" this HTML so that it's not easily read?

Second thought...

Several years ago, we had a spammer who was hitting our site harassing our members, so I isolated his IP and redirected him to a special page which spawned an additional window which spawned an additional window etc and it would actually crash a computer because the windows came up faster than you could close them... this was in the days before pop-up blockers..

I don't suppose this technique would work anymore, but would it be possible to somehow detect these attempts by seeing the bcc: in the field and doing something similar to slow him down or even crash his computer? Endless windows works well if they can still be spawned... haven't tried it for a long time...



 11:52 pm on Sep 13, 2005 (gmt 0)

well I wouldn't recommmend crashing anyone's computer, given that is the same illegal type of activity that we are trying to prevent. ;)

there are some other thoughts in this thread

msg 19 shows exactly what you are talking about, it's perl syntax but very similar in php, you are looking for a newline or carriage return in the field that is posted.

>> I assume they're using a search engine

it's all about footprints and poorly protected scripts. If you are using someone's distributed script you need to scrub every identifying mark from the script filenames, comments (viewable in a browser), common html and anything else that can identify that script in a search.

You also need to be sure that the script's validation/protection are up to snuff. Never trust anyone else's coding, why gamble? Most of them are fairly simple and can be run through and figured out how they work in an hour or two.

If you roll your own, better do it right, no need to do validation from scratch there are tons of classes and/or libraries already available. Again, make sure you understand what it is doing, I have never used anyone else's script that I haven't changed something.


 12:52 am on Sep 14, 2005 (gmt 0)

"Crashing" is a bit of a stretch... it just spawned so many windows that the computer became unusable until you rebooted. If this is a spammer, seems to me that if you could delay him for a while it would make the world a better place.



 12:56 am on Sep 14, 2005 (gmt 0)

I prefer redirecting to internet crime unit sites and the like, always seems appropriate. ;)

This 51 message thread spans 2 pages: 51 ( [1] 2 > >
Global Options:
 top home search open messages active posts  

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved