Make secure contact form from Spam Robot

1) One of the most common problems when having any kind of forms on a site is receiving spam. The more popular the site is, the more likely it will become a target for spamming entities and more difficult is to stop form spam.

The use of Captcha is an easy and effective way of fighting spam but it comes with a cost which our users have to pay, and this is fulfilling one more step in the process.

Firstly, I add a field to the form and this will be my HoneyPot field. The important thing here is to make our new field to blend in. For our example, I’m going to add the “Phone number” and the label text should be “Leave this field empty”. The specific label text is for the users in browsers with the CSS disabled, so they know they have to leave it empty.

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
  <label>Full name:</label>
    <input type="text" name="fullName" />
   <label>Email address:</label>
    <input type="email" name="emailAddress" />
    <label class="hide">Leave this field empty:</label>
    <input class="hide" type="text" name="phoneNumber6tY4bPYk" autocomplete="off" />
    <label>Your message</label>
    <textarea name="message"></textarea>
    <input type="submit" name="submit" value="submit">
	</form>
	<style type="text/css">
	 .hide{
		display: none;
	}

Two important things to notice.
The input field has autocomplete=”off”. The name attribute is “phoneNumber6tY4bPYk”, it contains a small hash after the “phoneNumber” part. This is to keep the browsers from inserting data by default or autocompletion.

In addition, I make then new field invisible by CSS:

Now, let’s take a look to the backend validation. I check the HoneyPot field value ($honeyPot). If it’s not empty, the most probable is that the form was sent by a spam robot:

<?php 
if(isset($_POST['submit']) && $_POST['submit']!="")
{ 
$honeyPot = $_POST['phoneNumber6tY4bPYk']; 
if (trim($honeyPot) != '') 
{ 
// This is a spam robot. Take action! echo "This is a spam robot"; 
} 
else
{ 
echo "this is a human"; 
} // It's a human. Continue with the rest of the validation. } 
?>

2) Time Measuring technique. Stop form spam on the clock!

The spam robots are very fast and that’s one of their features which they use to their advantage, but we can turn the things around using their speed to make them stand out and detect them.

In order to do that, I added a new field to our form. It has to be a hidden field and the value is the encrypted timestamp of the time when the form was loaded:

<?php require “encryptor.php”; ?>
<form action=”backend.php” method=”post”>
<input type=”hidden” name=”formLoaded6tY4bPYk” value=”<?php echo Encryptor::encrypt(time()) ?>” />
<label>Full name:</label>
<input type=”text” name=”fullName” />
<label>Email address:</label>
<input type=”email” name=”emailAddress” />
<label class=”hide”>Leave this field empty:</label>
<input class=”hide” type=”text” name=”phoneNumber6tY4bPYk” autocomplete=”off” />
<label>Your message</label>
<textarea name=”message” />
</form>

 

<?php
class Encryptor {
static function encrypt($value) {
$encryptedValue = base64_encode($value);
return $encryptedValue;
}

static function decrypt($value) {
$decryptedValue = base64_decode($value);
return $decryptedValue;
}
}

The validation

require “encryptor.php”;

define(“MIN_TIME_TO_FILL_FORM”, 5); // define the minimum time required to fill the form to 5 seconds

$honeyPot = $_POST[‘phoneNumber6tY4bPYk’];
$encryptedLoadedFormTime = $_POST[‘formLoaded6tY4bPYk’];

$loadedFormTime = Encryptor::decrypt($encryptedLoadedFormTime); // decrypt it
$formFilledInSeconds = time() – $loadedFormTime;

if (trim($honeyPot) != ”) {
// This is a spam robot. Take action!
exit(‘Spam Bot detected by HoneyPot’);
}

if(!isset($encryptedLoadedFormTime) || $formFilledInSeconds < MIN_TIME_TO_FILL_FORM) {
// This is a spam robot. Take action!
exit(‘Spam Bot detected by Time Measuring’);
}

// It’s a human. Continue with the rest of the validation.

As a result, I receive the parameter “formLoaded6tY4bPYk” (line 8) which has the encrypted timestamp when the form was loaded. I decrypt it (line 10), so I can use the current timestamp to know how long it took the user to fill the form (line 11).
Furthermore, I make sure I receive the value of the field, and that the user didn’t spend less time than the minimum defined earlier (line 18).

3)  $_SERVER['HTTP_USER_AGENT']; to check if the agent is said spider.

<?php
function crawlerDetect($USER_AGENT)
{
$crawlers = array(
'Google' => 'Google',
'MSN' => 'msnbot',
      'Rambler' => 'Rambler',
      'Yahoo' => 'Yahoo',
      'AbachoBOT' => 'AbachoBOT',
      'accoona' => 'Accoona',
      'AcoiRobot' => 'AcoiRobot',
      'ASPSeek' => 'ASPSeek',
      'CrocCrawler' => 'CrocCrawler',
      'Dumbot' => 'Dumbot',
      'FAST-WebCrawler' => 'FAST-WebCrawler',
      'GeonaBot' => 'GeonaBot',
      'Gigabot' => 'Gigabot',
      'Lycos spider' => 'Lycos',
      'MSRBOT' => 'MSRBOT',
      'Altavista robot' => 'Scooter',
      'AltaVista robot' => 'Altavista',
      'ID-Search Bot' => 'IDBot',
      'eStyle Bot' => 'eStyle',
      'Scrubby robot' => 'Scrubby',
      'Facebook' => 'facebookexternalhit',
  );
  // to get crawlers string used in function uncomment it
  // it is better to save it in string than use implode every time
  // global $crawlers
   $crawlers_agents = implode('|',$crawlers);
  if (strpos($crawlers_agents, $USER_AGENT) === false)
      return false;
    else {
    return TRUE;
    }
}
?>
<?php $USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
  if(crawlerDetect($USER_AGENT)) return "no need to lang redirection";?>

 

4) Put a hidden link in the footer of your website that links to a page that collects user-agents and/or IP addresses. Users won’t see this but bots will. So anyone who visits that page will be a bot. Record them and then block them from your stats.

Please follow and like us:

Leave a Reply

Your email address will not be published. Required fields are marked *