Forum Moderators: coopster

Message Too Old, No Replies

Contact Form Validation

checking for http and www

         

LinusIT

5:18 pm on Jan 17, 2011 (gmt 0)

10+ Year Member



Hi

I've got a php script I use for sending emails from a form. It works fine but a few times a week I get a spammy message, every field contains a url and the message part is full of urls. It doesn't do any harm apart from just being annoying.

Is there anyway of checking for http or www on processing and if present redirect back to the contact page?

Here's the code I use for sending the message:


$to = "yourname@myemail.com";
$email = $_REQUEST['contact_email'] ;
$from = $_REQUEST['contact_firstname'] ;
$name = $_REQUEST['contact_surname'] ;
$headers = "From: $email";
$subject = "Enquiry";

$fields = array();
$fields{"contact_firstname"} = "Firstname";
$fields{"contact_surname"} = "Surname";
$fields{"contact_email"} = "Email";
$fields{"contact_subject"} = "Subject";
$fields{"contact_message"} = "Message";

$body = "We have received the following information:\n\n"; foreach($fields as $a => $b){ $body .= sprintf("%20s: %s\n",$b,$_REQUEST[$a]); }

rocknbil

6:51 pm on Jan 19, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That form is horribly insecure; *you* may only be getting one, but it is wide open to injection in which a multipart email may be injected to mail thousands of recipients where you only get one.

But to answer the question, some of which will fix that,

Define this somewhere at the top.You can put it right after $fields{"contact_message"} = "Message";


$bad_patterns = Array (
'b*cc\s*:',
'to\s*:',
'content\-type',
'\[\s*URL.*\]*',
'\[\s*LINK.*\]*',
'\%5B\s*URL.*(\%5D)*',
'\%5B\s*LINK.*(\%5D)*',
'\[\s*a\s*href.*\]*',
'\%5B\s*a\s*href.*(\%5B)*',
'\<\s*a\s*href.*\>*',
'\%3C\s*a\s*href.*(\%3E)*',
'viagra' // Note no comma on LAST ONE
);
foreach ($_REQUEST as $key=>$value) {
filter_spam($bad_patterns,$value);
}


Then drop this in the BOTTOM of your script just before ?>


function filter_spam ($spam_patterns,$field) {
foreach ($spam_patterns as $v) {
if (preg_match("/$v/i",stripslashes($field))) {
die("Spam found in input, no email was sent.");
}
}
}


Make a backup copy first, this is not perfect, but it's a start.

LinusIT

9:06 pm on Jan 19, 2011 (gmt 0)

10+ Year Member



You've got me slightly worried now rocknbil :( I used this code on most of my sites, clearly not knowing how unsecure it was, oooops.

I've tried doing what you suggested but it doesn't work. It displays a blank page when processing. I'll provide all the code used for sending the email. I would really appreciate it if you could help me on this one as once sorted I can "fix" the other sites contact code.


<?php
if ($_GET["mode"]=="send")
{
$to = "info@email.com";
$email = $_REQUEST['contact_email'] ;
$from = $_REQUEST['contact_firstname'] ;
$name = $_REQUEST['contact_surname'] ;
$headers = "From: $email";
$subject = "Enquiry";

$fields = array();
$fields{"contact_firstname"} = "Firstname";
$fields{"contact_surname"} = "Surname";
$fields{"contact_phone"} = "Phone";
$fields{"contact_email"} = "Email";
$fields{"contact_subject"} = "Subject";
$fields{"contact_message"} = "Message";

$bad_patterns = Array (
'b*cc\s*:',
'to\s*:',
'content\-type',
'\[\s*URL.*\]*',
'\[\s*LINK.*\]*',
'\%5B\s*URL.*(\%5D)*',
'\%5B\s*LINK.*(\%5D)*',
'\[\s*a\s*href.*\]*',
'\%5B\s*a\s*href.*(\%5B)*',
'\<\s*a\s*href.*\>*',
'\%3C\s*a\s*href.*(\%3E)*',
'viagra' // Note no comma on LAST ONE
);
foreach ($_REQUEST as $key=>$value) {
filter_spam($bad_patterns,$value);
}

$body = "We have received the following information:\n\n"; foreach($fields as $a => $b){ $body .= sprintf("%20s: %s\n",$b,$_REQUEST[$a]); }

$headers2 = "From: info@email.com";
$subject2 = "Thank you for contacting us";
$autoreply = "Thank you for contacting us. Somebody will get back to you as soon as possible, usually within 24 hours. If you have any more questions, please consult our website at www.site.com";

$send = mail($to, $subject, $body, $headers);
$send2 = mail($email, $subject2, $autoreply, $headers2);
if($send)
{header( "Location: [site.com...] );}
else
{print "We encountered an error sending your mail, please notify info@email.com"; }

function filter_spam ($spam_patterns,$field) {
foreach ($spam_patterns as $v) {
if (preg_match("/$v/i",stripslashes($field))) {
die("Spam found in input, no email was sent.");
}
}
}
}
?>

rocknbil

2:20 am on Jan 20, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Did you fix this? you missed a quote.

{header( "Location: [site.com...] );}
s/b
{header( "Location: [site.com...] ");}

I said put the function at the bottom. You have it inside this

if ($_GET["mode"]=="send")
{
// See? Your function is in here!
}
// and it should be HERE
?>

What you should have gotten is "fatal call to undefined function filter_spam" but since you didn't, I can only assume that your form is not sending mode=send:

<input type="hidden" name="mode" value="send">

What that will give you, since the whole thing is wrapped in the above if, is . . . a white page. An "else" for error trapping is good insurance.

if ($_GET["mode"]=="send")
{
// the rest of the code WITHOUT the function
}
else { echo "Ahh. Bill's on to something here."; }

// function goes HERE, outside your if/else

?>

:-)

LinusIT

11:32 am on Jan 20, 2011 (gmt 0)

10+ Year Member



Thanks rocknbil.

I haven't missed a quote on the header line, it's just the way the forum has shortened the URL.

I've moved the function to the bottom of the script and it works now. I've tested it but I'm still able to type www.blah.com and the form gets sent. If I type in viagra then the Spam found message appears.

rocknbil

4:32 pm on Jan 20, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You can modify this array to suit your needs. The items listed in it are "the most common" (that I have witnessed, over the years) patterns spammers use when automating form attacks. They are generally in the form of forum links or full HTML URL's. Try adding the bolded line. Note this is a regular list array -items are separated by commas, the last one none.

$bad_patterns = Array (
'b*cc\s*:',
'to\s*:',
'content\-type',
'\[\s*URL.*\]*',
'\[\s*LINK.*\]*',
'\%5B\s*URL.*(\%5D)*',
'\%5B\s*LINK.*(\%5D)*',
'\[\s*a\s*href.*\]*',
'\%5B\s*a\s*href.*(\%5B)*',
'\<\s*a\s*href.*\>*',
'\%3C\s*a\s*href.*(\%3E)*'
'(www\.)?[^\.]+\.[a-z]{2,}',
'viagra' // Note no comma on LAST ONE
);


These are passed to the filter spam routine where they are used in a case-insensitive pattern match (which is why you DON'T need [A-Za-z].) You may need to fiddle with it, but pretty sure the breakdown of the new rule is

(www\.)? - zero or one of the parenthesized pattern (i.e., with or without www). In regexps, . means "any character" so we escape it to match a literal dot.

[^\.]+ - followed by one or more of anything NOT a dot
\. - followed by at least one dot

[a-z]{2,} - followed by 2 or more letters - this is a bit open ended to attempt a match.on.subdomain url's. It should capture .ro, .com, .net . . . .

This is untested but it's a start, play with it.

LinusIT

8:42 pm on Jan 21, 2011 (gmt 0)

10+ Year Member



It works :) thanks very much. Also thank you for the detailed explaination, I understand how it works now.

I have one more question, is there a way of redirecting the user back to the page or to say contact-us.php?mode=spam, instead of displaying a white page with the spam found message?