Halfway decent spam stopper for forms

RJM62

Touchdown! Greaser!
Joined
Jun 15, 2007
Messages
13,157
Location
Upstate New York
Display Name

Display name:
Geek on the Hill
I have put together a halfway decent PHP spam stopper for contact forms. Briefly, this is what it does:

1. Compares the epoch time when the form loaded to the time when the contact form script is called, and kills it if less than eight seconds have transpired. (Robots would probably fill the form in less than eight seconds.)

2. Sets up a bogus captcha trap in an invisible DIV ("id "swizzle" in the code posted below). Because robots generally ignore CSS, they will see the field and fill it in. If the value matches a random number generated by the script and presented as if it were a captcha, the script dies.

3. Checks the value of information entered into the bogus captcha field for "http://" or "@." If it contains those strings, the script dies.

4. Gets the client IP address at both the form and the processor stage. If they don't match, the script dies.

A working example of the script can be found at www.rjmwebdesign.com/spamproof.php . Here's code for both pages:


Code for sending (form) page:

HTML:
<?php
$start = time();
$captcha = rand();
$ip1=$_SERVER['REMOTE_ADDR'];
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Spamproof</title>
<link href="styles/mainstyle.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="form">
  <form action="sizzle.php" method="post">
    <div id="swizzle">
      <?php
        echo $captcha, '<br />';
        echo '<input type="text" name="haha" size="15" />', " ", 'Ignore this field if you are human<br />';
        echo '<input type="hidden" name="start" value="', $start, '"> <br />';
        echo '<input type="hidden" name="ip1" value="', $ip1, '"> <br />';
        echo '<input type="hidden" name="captcha" value="', $captcha, '"> <br />';
      ?>
    </div>
    <input type="text" name="stuff" size="25" />
    Please write some stuff in the line and take your time. <br />
    <input name="submit" type="submit" value="Send" />
    </p>
  </form>
</div>
</body>
</html>
Here's the PHP for the processing page:

PHP:
<?php
foreach($_POST AS $key => $value) {
    ${$key} = $value;
}
foreach($_GET AS $key => $value) {
    ${$key} = $value;
}
// get current epoch time
$timeNow = time();
// get IP address
$ip2=$_SERVER['REMOTE_ADDR'];
// get captcha response
$haha = Trim(stripslashes($_POST['haha']));
// die if submission is too fast for a human
if ($timeNow - $start < 8)
{
echo "Test failed. Less than eight seconds elapsed between when you loaded the form and when you submitted it.";
die;
// die if IP addresses don't match
} elseif ($ip1 !== $ip2)
{
echo "The IP addresses do not match. Test failed.";
die;
// die if captcha trap is filled in
} elseif ($captcha == $haha)
{
echo "The invisible captcha form was filled in. Test failed.";
die;
} elseif ($captcha == $haha)
{
echo "The invisible captcha form was filled in. Test failed.";
die;
}
// die if captcha field contains http:// or @
if (preg_match('@^(?:http://)?([^/]+)@i', $haha))
{
die;
}
echo "<strong>All tests passed!</strong><br /><br />";
echo "<strong>Test 1: Time</strong><br />";
echo "The epoch time when the form was loaded was ", $start, "<br />";
echo "The epoch time when the form was submitted was ", $timeNow, "<br />";
echo "It took ", ($timeNow - $start), " seconds to submit the form. A robot would have been faster.";
echo "<br /><br />";
echo "<strong>Test 2: Captcha Trap</strong><br />";
echo "'", $captcha, "'", " was the random number generated for the captcha trap.<br />";
echo "' ", $haha, "'", " was entered in the captcha trap field.<br />";
echo "Because ", $captcha, " does not equal ", "' ", $haha, "'", ", it doesn't appear that a robot filled this form.";
echo "<br /><br />";
echo "<strong>Test 3: Forbidden Characters</strong><br />";
echo "The value of the invisible string 'haha' is ", "' ", $haha, "' ", ". It does not contain http:// or @.<br /><br />";
echo "<strong>Test 4: IP Test</strong><br />";
echo "The form was submitted by IP Address ", $ip1, "<br />";
echo "The processing script was called by IP Address ", $ip2, "<br />";
echo "The IP addresses match.";
echo "<br /><br />";
$stuff = Trim(stripslashes($_POST['stuff']));
echo "Ohh... by the way... here is the stuff you entered:  ", $stuff;
?>
Comments Welcome.

Best,

Rich
 
Last edited:
Some input:

You don't define the variable on line 6 of form.php which throws an error on a default install of PHP5
Code:
[B]Notice[/B]:  Undefined variable: captcha in [B]/var/www/virtual/gastonsflyin.com/html/rich/form.php[/B] on line [B]6[/B]
Your code example doesn't work either. You're trying to echo variables into the HTML form and I don't know where you're getting those variables from? $ip1, $captcha, $start ?? Since these varibles don't exist--it throws errors into the HTML that gets rendered:

Code:
<body>
<div id="form">
  <form action="sizzle.php" method="post">
    <div id="swizzle">
      <br />
<b>Notice</b>:  Undefined variable: captcha in <b>/var/www/virtual/gastonsflyin.com/html/rich/form.php</b> on line <b>6</b><br />
<br /><input type="text" name="haha" size="15" /> Ignore this field if you are human<br /><input type="hidden" name="start" value="<br />
<b>Notice</b>:  Undefined variable: start in <b>/var/www/virtual/gastonsflyin.com/html/rich/form.php</b> on line <b>8</b><br />
"> <br /><input type="hidden" name="ip1" value="<br />
<b>Notice</b>:  Undefined variable: ip1 in <b>/var/www/virtual/gastonsflyin.com/html/rich/form.php</b> on line <b>9</b><br />
"> <br /><input type="hidden" name="captcha" value="<br />
<b>Notice</b>:  Undefined variable: captcha in <b>/var/www/virtual/gastonsflyin.com/html/rich/form.php</b> on line <b>10</b><br />
"> <br />    </div>
    <input type="text" name="stuff" size="25" />
    Please write some stuff in the line and take your time. <br />
    <input name="submit" type="submit" value="Send" />
    </p>
  </form>
</div>
Basically--none of this makes sense to me--you must not be including a lot of your code, Right? The foreach loops are a bad idea too--you cannot be trusting the input of the user.

What is the purpose of stripslashes on $_POST['haha'] ??

I'm not trying to be harsh--I'm just confused by what you posted..as this clearly can't be all the code.
 
I left out part of the first page the first time I posted it, Jesse. I edited it since. Please check it again (top of first page).

I'll have to remove the stripslashes. That was just a plain, old mistake.

Thank you,

Rich
 
I really do appreciate your input, Jesse. This is a work-in-progress. What happened is that I have been thinking about providing an emergency button on my forms that will send a text message to a cell phone, but I want to be as sure as I can to kill the bots first. Any advice will be gratefully accepted.

Rich
 
Here are the complete pages (except for the stylesheet, which I figure you've snagged already).
 

Attachments

  • spamstopper.zip
    1.8 KB · Views: 0
I'd love to know what I could do to stop the spam coming to me through Charter.net. I stopped downloading mail straight to Outlook but still delete a LOT through web mail.

Now, as if things aren't enough of a pain, Charter has started putting advertising on the web page for mail and just this week now has pop-ups for MORE advertising. Thankfully, Google blocker stops the pop-ups quite well.

I'd love the ability to anonymously redirect spam to the CEO of Charter. I hate it that I'm paying a fortune for web access then still get slammed with more advertising to use it.
 
If you're using Windows, Mailwasher Pro helps... but only when using a standard email client.

Time for bed. I'm going to see if I can get some flying in tomorrow morning, though the weather doesn't seem promising. Good night.

Rich
 
If you're using Windows, Mailwasher Pro helps... but only when using a standard email client.

Time for bed. I'm going to see if I can get some flying in tomorrow morning, though the weather doesn't seem promising. Good night.

Rich
Thanks Rich. I'll look into it.

I hope ya get those hours logged. I'm gonna wake up just long enough in the morning to tell "Her Majesty", the traffic queen we're not flying.
 
I 'hacked' your script. You can submit against this form as fast as you want and it'll hit your PHP logic on your server. Essentially I could blast you with as much spam as I wanted now--as fast as I wanted.

There are some flaws in your logic. This is perfectly normal to make mistakes like this starting out in web development. You really need to 'think' about what is technically possible--not what your GUI permits--because people aren't forced to your GUI to hit your logic.

There are some really good ways to fix this. But telling you these ways isn't how you learn. Take a look at my form and you'll see how I'm doing it. From there try and think of a way to stop it. It's important to grasp this stuff as it applies to any web code you ever write. Once we get this problem fixed we can move on to some other potential issues.

http://www.gastonsflyin.com/rich/formhack.php

Code:
<?php
$start = time();
$captcha = rand();
$ip1=$_SERVER['REMOTE_ADDR'];
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Spamproof</title>
<link href="styles/mainstyle.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="form">
  <form action="http://www.rjmwebdesign.com/sizzle.php?start=1&ip1=<?php echo($ip1); ?>&captcha=123123" method="post">
<div id="swizzle"><?php    echo '<input type="text" name="haha" size="15" />', " ", 'Ignore this field if you are human<br />'; ?> </div>
    <input type="text" name="stuff" size="25" />
    Please write some stuff in the line and take your time. <br />
    <input name="submit" type="submit" value="Send" />
    </p>
  </form>
</div>
</body>
</html>
?>
 
Last edited:
I'll post them in a little while.Okay, Jesse, I see some of what you've done and have made some changes, and am making a couple more since the WX is no-go for flying today (and maybe for field work, as well; I only have one stop, and I'm thinking about canceling it). Thank you.

This is a script to trap robots. I wasn't thinking in terms of "hacking" so much as simply fooling dumb bots. So you're right: I need to examine it from that perspective, as well. To create a vulnerability to fool a bot is a bad trade-off.

Also, if I were actually implementing this script, all of the explanatory stuff would be gone. Instead, there would just be something like " echo "Thank you for your submission."; " before each "die;" , not a message that the submission had been dumped.

Thanks again. Will post revised code shortly.

Rich
 
Okay, here's what I have so far:

Form page:

HTML:
<?php
unset($start, $captcha, $ip1, $haha, $stuff);
$start = time();
$captcha = rand();
$ip1=$_SERVER['REMOTE_ADDR'];
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Spamproof</title>
<link href="styles/mainstyle.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="form">
  <form action="sizzle.php" method="post">
    <div id="swizzle">
      <?php
        echo $captcha, '<br />';
        echo '<input type="text" name="haha" size="15" />', " ", 'Ignore this field if you are human<br />';
        echo '<input type="hidden" name="start" value="', $start, '"> <br />';
        echo '<input type="hidden" name="ip1" value="', $ip1, '"> <br />';
        echo '<input type="hidden" name="captcha" value="', $captcha, '"> <br />';
      ?>
    </div>
    <input type="text" name="stuff" size="25" />
    Please write some stuff in the line and take your time. <br />
    <input name="submit" type="submit" value="Send" />
    </p>
  </form>
</div>
</body>
</html>

Form Processor PHP Code:

PHP:
<?php
foreach($_POST AS $key => $value) {
    ${$key} = $value;
}
// get current epoch time
$timeNow = time();
// get IP address
$ip2=$_SERVER['REMOTE_ADDR'];
// get visible form field(s)
$stuff = $_POST['stuff'];
// get captcha response
$haha=$_POST['haha'];
// die if submission is too fast for a human
if ($timeNow - $start < 8)
{
echo "Test failed. Less than eight seconds elapsed between when you loaded the form and when you submitted it.";
die;
// die if IP addresses don't match
} elseif ($ip1 <> $ip2)
{
echo "The IP addresses do not match. Test failed.";
die;
// die if captcha trap is filled in
} elseif (!empty($haha))
{
echo "The invisible captcha form was filled in. Test failed.";
die;
// die if form field that shouldn't contains http
}
if (preg_match("/http/i", $stuff))
{
echo "Test failed. A field that should not have contained 'http' contained 'http'. The form was most likely filled out by a robot.";
die;
}
else;
echo "<strong>All tests passed!</strong><br /><br />";
echo "<strong>Test 1: Time</strong><br />";
echo "The epoch time when the form was loaded was ", $start, "<br />";
echo "The epoch time when the form was submitted was ", $timeNow, "<br />";
echo "It took ", ($timeNow - $start), " seconds to submit the form. A robot would have been faster.";
echo "<br /><br />";
echo "<strong>Test 2: Captcha Trap</strong><br />";
echo "'", $captcha, "'", " was the random number generated for the captcha trap.<br />";
echo "' ", $haha, "'", " was entered in the captcha trap field.<br />";
echo "It doesn't appear that a robot filled this field.";
echo "<br /><br />";
echo "<strong>Test 3: Forbidden Characters</strong><br />";
echo "The value entered for the visible field 'stuff' was ", "' ", $stuff, "' ", ", which does not contain 'http'.<br /><br />";
echo "<strong>Test 4: IP Test</strong><br />";
echo "The form was submitted by IP Address ", $ip1, "<br />";
echo "The processing script was called by IP Address ", $ip2, "<br />";
echo "The IP addresses match.";
echo "<br /><br />";
$stuff = Trim(stripslashes($_POST['stuff']));
echo "Ohh... by the way... here is the stuff you entered:  ", $stuff;
unset($start, $captcha, $ip1, $ip2, $haha, $stuff, $timeNow);
?>

Thanks again. If we can get this fixed, I think it could be quite useful

Best,

Rich
 
I think I should also unset the vars as the first line of the processor...
 
...
Also, if I were actually implementing this script, all of the explanatory stuff would be gone. Instead, there would just be something like " echo "Thank you for your submission."; " before each "die;" , not a message that the submission had been dumped.

One parameter early on for spam blocking is give no indication anything out of the ordinary is happening. Give the same response as you would for a legit user and then quietly dump the spam and block the spammer, provided doing so doesn't tie up your resources too much.

That way you tie up the jerk for a while and the only way he'd have to know it wasn't working would be by salting test data into the spam and seeing if it worked.
 
Last edited:
I was just thinking exactly the same thing. On a real form on a production site, I would make a clone of the "real" landing page, and dump the spammers into that page. This way even if a human tests a bot on the form, it looks like the submission succeeded.

Thank you, Mike. I appreciate your input. I was trained in electronics, not anything remotely related to programming; so every day is a new learning experience.

Best,

Rich

One parameter early one for spam blocking is give no indication anything out of teh ordinary is happening. Give the same response as you would for a legit user and then quietly dump the spam and block the spammer, provided doing so doesn't tie up your resources too much.

That way you tie up the jerk for a while and the only way he'd have to know it wasn't working would be by salting test data into the spam and seeing if it worked.
 
Or better yet, dump them onto the real landing page; but kill the script before it actually sends the mail!

I was just thinking exactly the same thing. On a real form on a production site, I would make a clone of the "real" landing page, and dump the spammers into that page. This way even if a human tests a bot on the form, it looks like the submission succeeded.

Thank you, Mike. I appreciate your input. I was trained in electronics, not anything remotely related to programming; so every day is a new learning experience.

Best,

Rich
 
Rich,

The main problem still remains. Don't think about the GUI you built--think about the GUI you could build that could take advantage of your logic.

Some food for thought: generate a unique completely random ID when the form loads. Place this ID in the database and in your html form. Now when that form hits your form logic your form logic can compare that ID to the database and pull out the IP address and the time that the ID was generated. Now you can compare the time and there is *no* way the user can influence that. The only data in the form should be data that you don't mind a user messing with--like their text. Make sure an ID can only be used once.

The important thing is to make sure that the data the user can influence is *THE ONLY DATA* you want them to influence. You might say this is overkill--but it is good practice to build everything you build *right*. If you code this stuff right you'll be able to use it throughout the future without reinventing the wheel.
 
Hmmm... so make the whole form database-driven, in a sense... I never really considered that, but it makes perfect sense, and would not be at all difficult, really. A little tedious, perhaps, but very secure and, as you say, recyclable.

You're right, though, when you mentioned that idea, the first thing that I thought was, "Does this guy realize that all I'm talking about is an email contact form that will trap bots?" I'm not sure I've ever come across a database-driven email form. IN fact, a lot of the ones I've seen are even more primitive than my 1970's-era logic.

But it does make sense. Rather than just trying to trap what's out there now, a few hours work could result in something that not only would trap today's bots, but would be much more difficult to teach future bots to evade.

Great idea, Jesse. Now I have another project to work on. Judging by the WX forecast for this week coming, I should have some time to work on it, too.

Thanks again,

Rich

Rich,

The main problem still remains. Don't think about the GUI you built--think about the GUI you could build that could take advantage of your logic.

Some food for thought: generate a unique completely random ID when the form loads. Place this ID in the database and in your html form. Now when that form hits your form logic your form logic can compare that ID to the database and pull out the IP address and the time that the ID was generated. Now you can compare the time and there is *no* way the user can influence that. The only data in the form should be data that you don't mind a user messing with--like their text. Make sure an ID can only be used once.

The important thing is to make sure that the data the user can influence is *THE ONLY DATA* you want them to influence. You might say this is overkill--but it is good practice to build everything you build *right*. If you code this stuff right you'll be able to use it throughout the future without reinventing the wheel.
 
Hey Jesse,

I haven't had much time to work on this the past few days, but in the time I had, it morphed into something more than what I had in mind.

My original idea was to create a mailto script that was as bot-proof as possible because it would be specifically used for emergency messages that would be sent as text messages to a cell phone, which most people have to pay for.

Based on your suggestion, I built a database-driven version that actually did work, but then I scrapped it. The reason was because I was only using the database for the validation step. But because text messages are small and I had built a database anyway, I decided to store ALL of the form data in the database. This way it provides a running record of how many bots got through and how many false positives there were, as well as a way to retrieve the false positives.

This is good practice. I haven't dealt with very much database stuff in a long time. The last database-driven Web app I wrote from scratch was more than a year ago, and I'm amazed (and distressed) at how much of even the basics I've forgotten in the interim.

I'm also basically a nice guy (these days, anyway; I have mellowed with age), and working on something like this forces me to think a bit more deviously than I am accustomed to, which is an unfortunate necessity in this business, these days.

So thanks again. I really needed the practice, even if the end result turns out to be "overkill." Hopefully I'll have something to show you in a few days; and I owe you a decent meal the next time you're in NYC.

Best,

Rich
 
Okay, here is the new version. Some of the code may be a bit ugly and in need of cleaning, but it does work.

http://www.rjmwebdesign.com/sandbox/spamstop/spamstop.php

And the code:

The main form page:

PHP:
<?php
include ("initialize.php");
include ("header.php");
include ("body.php");
?>
The initializer script, initialize.php, that sets the initial vars, gets the time, and hashes the unique user id:

PHP:
<?php
$start_time = time();
$ip1=$_SERVER['REMOTE_ADDR'];
$captcha = rand(10000, 99999);
$unique_user = md5($start_time . "_" . $captcha);
include ("open_db.php");
mysql_query("INSERT INTO requests (start_time, captcha, ip1, unique_user) VALUES ('$start_time', '$captcha' , '$ip1' , '$unique_user')") 
or die("recorder Could not insert data");
?>
The header, header.php:

HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script language="javascript" type="text/javascript">
function limitText(limitField, limitCount, limitNum) {
    if (limitField.value.length > limitNum) {
        limitField.value = limitField.value.substring(0, limitNum);
    } else {
        limitCount.value = limitNum - limitField.value.length;
    }
}
</script>
</head>
The body, body.php:

HTML:
<body>
<noscript>
NOTE: You appear to have JavaScript disabled (or an ad-blocker is interfering with it). This form may not work properly with JavaScript disabled.
</noscript>
<p>In an emergency, you can use this form to send a text message. Due to the size  limits on a  text message, the message body must not exceed 100 characters.</p>
<p>&nbsp; </p>

<form action="collector.php" method="post" enctype="multipart/form-data" name="form">
  <p>
    <input name="name" type="text" size="30" maxlength="30" />
    Name * </p>
  <p> (
    <input type="text" name="areacode" size="3" maxlength="3" />
    )
    <input type="text" name="phone" size="8" maxlength="8" />
    &nbsp;Ext.
    <input type="text" name="ext" size="6" maxlength="6" />
    Phone Number *</p>
  <p>
    <input type="text" name="site" size="30" maxlength="30" />
    Site or domain, if applicable. </p>
  <div id="stronza"> <?php echo $captcha, '<br />'; ?>
    <input name="verifier" type="text" size="30" maxlength="60" />
  </div>
    <input type=hidden name="unique_user" value="<?php echo($unique_user)?>">
  <p>
    <textarea name="message" cols="30" rows="4" onKeyDown="limitText(this.form.message,this.form.countdown,100);" 
onKeyUp="limitText(this.form.message,this.form.countdown,100);">
</textarea>
    Message<br>
    <font size="1">(Maximum characters: 100)<br>
    You have
    <input readonly type="text" name="countdown" size="3" value="100">
    characters left.</font><br>
  </p>
  <p>&nbsp;</p>
  <p>
    <input type="submit" name="Submit" value="Text Me!" />
  </p>
  <p>&nbsp;</p>
</form>
</body>
</html>
And the guts of the script, collector.php:

PHP:
<?php
// get submission time and IP address
$timeSubmit = time();
$ip2=$_SERVER['REMOTE_ADDR'];
// collect variables
$name = $_POST['name'];
$areacode = $_POST['areacode'];
$phone = $_POST['phone'];
$ext = $_POST['ext'];
$site = Trim(stripslashes($_POST['site']));
$message = Trim(stripslashes($_POST['message']));
$user = $_POST[unique_user];
$submitter = $user;
// get bogus captcha response
$verifier = $_POST['verifier'];
// check to see if form fields filled in
$complete=true;
if (empty ($name)) $complete=false;
if (empty ($areacode)) $complete=false;
if (empty ($phone)) $complete=false;
if (empty ($message)) $complete=false;
if (!$complete)
{
/*print "<meta http-equiv=\"refresh\" content=\"0;URL=error.html\">"; */
echo "A required field was left blank.";
}
else
{ 
// we populate the row so as to have a record of the attempt and do later tests
include ("open_db.php");
mysql_query ("UPDATE requests SET submitter='$submitter', name='$name', submit_time='$timeSubmit', ip2='$ip2', areacode='$areacode', phone='$phone', ext='$ext', site='$site', verifier='$verifier', message='$message' WHERE unique_user='$user'")
or die("Collector could not update data");
mysql_close();
}
?>

<?php
// Now we retrieve the data
include ("open_db.php");
$query="SELECT * FROM requests WHERE unique_user = '$user'";
$result=mysql_query($query);

// die if no match is found for the user before we waste any more time
if (empty($result))
{ echo "No match found for user";
die;
}
// now that we know the user exists, we assign the variables we'll need to do the bot checks
while($row = mysql_fetch_assoc($result))
{
$start_time=($row["start_time"]);
$captcha=($row["captcha"]);
$ip1=($row["ip1"]);
$unique_user=($row["unique_user"]);
$submitter=($row["submitter"]);
$name=($row["name"]);
$submit_time=($row["submit_time"]);
$ip2=($row["ip2"]);
$areacode=($row["areacode"]);
$phone=($row["phone"]);
$ext=($row["ext"]);
$site=($row["site"]);
$verifier=($row["verifier"]);
$message=($row["message"]);
mysql_close;
}
// now do the robot tests
if (($submit_time - $start_time < 8) || ($submit_time - $start_time > 300))
{
echo "Test failed. Less than eight seconds or more than 300 seconds elapsed between when you loaded the form and when you submitted it.";
die;
// die if IP addresses don't match
} elseif ($ip1 !== $ip2)
{
echo "The IP addresses do not match. Test failed.";
die;
// die if hashes don't match
} elseif ($unique_user !== $submitter)
{
echo "The hashes don't match for the form and the submission. Test failed.";
die;
// die if captcha trap is filled in
} elseif (!empty($verifier))
{
echo "The invisible captcha form was filled in. Test failed.";
die;
// die if form field that shouldn't contains http
}
if ((preg_match("/http/i", $name)) || (preg_match("/http/i", $message)))
{
echo "Test failed. A field that should not have contained 'http' contained 'http'. The form was most likely filled out by a robot.";
die;
}
else;
//this stuff is just here for testing. The actual form would have sent the message to the cell phone
echo "<strong>All tests passed!</strong><br /><br />";
echo "<strong>Test 1: Time</strong><br />";
echo "The epoch time when the form was loaded was ", $start_time, "<br />";
echo "The epoch time when the form was submitted was ", $submit_time, "<br />";
echo "It took ", ($submit_time - $start_time), " seconds to submit the form.";
echo "<br /><br />";
echo "<strong>Test 2: Captcha Trap</strong><br />";
echo "'", $captcha, "'", " was the random number generated for the captcha trap.<br />";
echo "' ", $verifier, "'", " was entered in the captcha trap field.<br />";
echo "It doesn't appear that a robot automatically filled this field.";
echo "<br /><br />";
echo "<strong>Test 3: Forbidden Characters</strong><br />";
echo "The string 'http' was not entered in the name or message fields.<br /><br />";
echo "<strong>Test 4: IP Test</strong><br />";
echo "The form was submitted by IP Address ", $ip1, "<br />";
echo "The processing script was called by IP Address ", $ip2, "<br />";
echo "The IP addresses and hashes match.";
echo "<br /><br />";
echo "Ohh... by the way... here is the message you entered:  ", $message;
exit;
?>
There's also open_db.php, which is just the SQL login.

The only machine-generated vars passed openly are the bogus captcha value (which we want a robot to try to copy), and the unique_user hash (which will cause the script to die if tampered with, if it doesn't match when compared later in collector.php, or if used more than 300 seconds after it was generated).

Note that the error message echos are purely for testing and illustration. In a real form, the mailer would send the mail if all the tests were passed.

Comments?

Best,

Richard
 
Hmmm... one thing that comes to mind from the submissions from people on the various boards where this is posted is that I could probably include additional code to keep a record of exactly which test was failed, for statistical purposes. That may be an interesting addition...

Rich
 
Also added unset vars at initialize.php:

PHP:
 <?php
unset ($start_time, $ip1, $captcha, $unique_user);
$start_time = time();
$ip1=$_SERVER['REMOTE_ADDR'];
$captcha = rand(10000, 99999);
$unique_user = md5($start_time . "_" . $captcha);
include ("open_db.php");
mysql_query("INSERT INTO requests (start_time, captcha, ip1, unique_user) VALUES ('$start_time', '$captcha' , '$ip1' , '$unique_user')") 
or die("recorder could not insert data");
?>
 
Rich,

Having watched you repeatedly post to yourself on this thread, I'd like to invite you to join us in Flashchat during the evenings. I think you're more than qualified.

We refer to our group as the "No Life Club." :)
 
Nice. I've been busy and haven't had a chance to look at this yet. I'll try to take a look tonight.
 
LOL, thanks.

Rich,

Having watched you repeatedly post to yourself on this thread, I'd like to invite you to join us in Flashchat during the evenings. I think you're more than qualified.

We refer to our group as the "No Life Club." :)
 
By the way, if anyone is actually still interested in this, the reason for ending and restarting in collector.php is because I have something else in mind to do at that point in the script when I have a chance. Basically, I want to test against and update a shared database of banned IP addresses. But because I'm busy with other projects right now, I haven't gotten around to it.

Rich
 
Back
Top