Welcome to WebmasterWorld Guest from

Forum Moderators: coopster & jatar k

Message Too Old, No Replies

Opinions on anti-spam solution

What are the weaknesses of my solution?

1:29 am on Nov 24, 2006 (gmt 0)

Junior Member

10+ Year Member

joined:Dec 18, 2004
votes: 0

I have recently implemented a simple php contact form for a client who had suffered header injection spam with the previous form. My solution is holding up well for now but I would like opinions from others experiences.

Rather than search for \r\n or to: cc: bcc: or content-type or . . . I decided to validate the single line entries and test the message contents to ensure that injection type data was just sent as a message and didn't create any additional messages.

The form has only four fields: name,email,subject,comments. What I did was to use regex to validate the first three:

Name ^([A-Z '-]+)$
Contains alphas, dashes, spaces and apostrophe for O'Malley. Names longer that 50 characters are truncated and have ... added

Subject ^([A-Z0-9 '-:\!\?]+)$
Similar to name with the addition of some punctuation. Long subjects are truncated in the same way as long names.

Note that neither of these fields can contain @ signs, CRLF characters or the % that the hex equivalents would contain.

This only allows one email address that I use as a reply-to but not as a from. No surprises created by replying to multiple email addresses. This will not allow a valid email address with a .museum domain but the client doesn't expect these. They would be allowed if I used (2,6) instead. At present, I am also truncating email addresses longer than 50 characters - I find it hard to imagine that a regular human user typing an email address into a box on a form could have an email address longer than 20 - 30 characters at the most.

For the actual message, I want to allow anything and preserve the crlf for formatting. I found that I could create an extra header if I a \r\nbcc:email@domain.com at the very end of the message. Then, when I added my \r\n to send the message, an email was sent to the injected address. To prevent this from happening, I just added a string at the end of the message. In my case, I added the IP address originating the form message. But pretty well any "end of message" string would work, it seems to me.

Magic_quotes are on and I strip_slashes before sending the data - also strip_tags, keeping \n (but not \r) for only the message and then replacing the \n with <br>\r\n to keep paragraph formatting. This seems to sometimes add extra paragraph spacing so if anyone has a comment about this I'd appreciate it.

I created test data using the types of header injection data described at


but using my own email addresses. I checked the headers of the email that arrived at the recipient and also checked to see whether any email arrived at my additional email addresses.

I know that they can be spoofed but I also check for valid referrers using $_SERVER['HTTP_REFERER'] and an actual (i.e. not blank) browser using $_SERVER['HTTP_USER_AGENT'] - should I bother or do most spammers spoof these?

I check that $_SERVER['REQUEST_METHOD'] is 'post' because I saw it suggested somewhere but I don't really understand the reasoning behind it so if anyone can enlighten me I would appreciate it.

To hopefully prevent flooding, the system uses a session variable to prevent another message being sent after the first one. If the user closes the browser and re-opens it, they can send a second message.

I calculated that most normal users would take about 30 seconds at the very least to type an entry in every field of the form and a couple of lines in the message so I added a time delay. I record a timestamp at the start of the session and calulate the elapsed time just before sending the message. If the elapsed time is less than 30 sec, I just sleep until the 30 sec is up. Actually, I had to sleep for 2 sec, output a blank and then sleep for 2 sec in a while loop or the browser created a time out.

If anyone wants to or is willing to test my form, I will give you a link to my test version of it if you PM me.

Is there anything different that people think I should be doing? Or? This is working right now but I am a relative novice at php and I am hoping that others who know more will have some comments on what I have come up with.

Thanks in advance for any/all comments.

9:16 am on Nov 26, 2006 (gmt 0)

Senior Member

WebmasterWorld Senior Member dreamcatcher is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Mar 30, 2003
votes: 0


Try this [webmasterworld.com] related thread.



Join The Conversation

Moderators and Top Contributors

Hot Threads This Week

Featured Threads

Free SEO Tools

Hire Expert Members