Securing your Contact Form

In the lesson before about making your contact form work, there was a warning on the bottom that said you should apply some security measures to your new script. Here we are going to outline some of the measures available to you, but it is in no way complete.

We will be talking about taking some measures to stop an e-mail injection attack, if you add a database to your script, there are other measures that you would want to take, but for this we are just talking about email injection attacks.

E-mail injection attacks usually involve the attacker inputting information into your form that the server will interpret as code, and not data, which can give the attacker the ability to use your site as a point of spam. Most of these attacks involve injection code to the headers of the script, giving them the ability to then send out thousands of emails from your account. This usually prompts a nasty notice from your host and could result in your host canceling your account, not very nice!

With injection attacks of a database, there is the potential for theft of data, loss of data, or a corruption of the database itself, so there are more measures and more robust measures created to stop the attacks, but again, this tutorial is dealing with e-mail injection attacks.

 

What they don’t know won’t hurt you.

Honey Pots

A honey pot is a very effective tool for stopping spam and injection attacks. Basically a honey pot employs inserting an hidden input field into your form, in your processing script you kill the script if the field is changed. The input field will be invisible to the human, but the evil bots will recognize an input field, and insert their spam message or malicious code, and the script dies.

We have 3 parts to the honey pot, one is in the HTML, one is in the PHP, the last is in the CSS.

  • In the html, within your form tag, insert the following:

    <div id=”important”>
    <label>Address</label>
    <input type=”text” name=”address” id=”address” />
    </div>

Here we have inserted a div tag named important with the input field called address.

  • In the CSS:

    <style type=”text/css”>
    #important {
    visibility: hidden;
    height:15px;
    }
    </style>

Here we have made the div tag name important invisible to the human surfer.

  • In the php:
    <?php
    // checks if bot

This says if the input field of address is not empty, kill the script. You can do different variations of this script, such as enter a value then instruct php that if the field is changed, kill the process, or you can to both.

Capture the bad guys with captcha!

We have all seen this, you fill out a form and there is the set of distorted letters and numbers that you must enter into a field. I personally don’t care for it because my failure rate of typing the correct characters in is about 50/50, however it does work. It is a free service you sign up for and can apply it to your form.

Basically how it works is that bots have a hard time reading characters in images,so the form will die when the bad bots run into it.

captcha.net

More information about Captcha

Stop the submission with tell tale intent.

Many e-mail injection attacks try to fool the server into thinking that the data in the form is code from the processing script. Specifically, they will insert rn, which tells the server to create a new line, where they can then insert a new mail recipient, or many new recipients. The following is a script I wrote that checks to see if these characters are in your data, and kills the script:

<?php

$newlinecounter = 0;
foreach($_POST as $key => $val_newline){
if(stristr($val_newline, 'r')){$newlinecounter++;}
if(stristr($val_newline, 'n')){$newlinecounter++;}
if(stristr($val_newline, 'r')){$newlinecounter++;}
if(stristr($val_newline, 'n')){$newlinecounter++;}
if(stristr($val_newline, 'rn')){$newlinecounter++;}
if(stristr($val_newline, 'rn')){$newlinecounter++;}
if(stristr($val_newline, 'Bcc')){$newlinecounter++;}
}
if ($newlinecounter >= 1){ die('die scum die');} ?>

A couple of points about this script. If you notice I have single and double backslashes, this is because many times, because of other security measures, in particular, magic_quotes, will change the number of slashes. Since there is no reasonable legitimate reason to include any slashes in a form submission, I have included the single and doubles.

If you notice, I put the line of text ‘die scum die’ as a message to the spammers. This might be funny, but it could spur them on to accept your challenge, so putting any kind of “I got you” message is not a good idea.

Not so Fast!

A couple of years ago I had a site up with a database that was attacked. Fortunately, it was an old site that was not being used and there was no damage, so I was lucky.

There first clue that I had been attacked is there were multiple, probably hundreds of submissions to the form, within seconds of each other. Some bot was probing the security and submitting hundreds of times to get in. It was interesting to see how it systematically inserted variations of the same code to see which version would work.

So now seeing that, we have a script that will kill the processing if there are too many submissions within a certain time frame, say 30 seconds, and another that will kill the processing if the same computer is visits the processing page more than a certain number of times. In the sample, I have it set to 10.

The information is saved in session variables, so once the browser is closed, the scripts are dead and upon opening again, the count would start over again. This is good incase you have a legitimate submitter that is making mistakes and re-submitting.

First, at the top of your page, above the DTD, insert the following code:

<?php
if (!isset($_SESSION)) {
session_start();
}
?>

This tells the server that if a session has not been started, start one now. If the session is already started, it ignores this and moves on. The second part is your actual script.

if(!isset($_SESSION[‘count’]))
{
$_SESSION[‘count’] = 1;
$_SESSION[‘first’] = time();
}
else
{
// Increase the Count
$_SESSION[‘count’]++;
// Reset every so often
if($_SESSION[‘first’] < (time() – 30))
{
$_SESSION[‘count’] = 1;
$_SESSION[‘first’] = time();{
die (“Too many”);
}
}
$ip = $_SERVER[‘REMOTE_ADDR’];
$_SESSION[‘$ip’] = 1;
$cal = ($_SESSION[‘$ip’] / $_SESSION[‘$ip’]);
$cal++;
// Die if they have viewed the page too many times
//if($_SESSION[‘count’] > 10)
if (($cal)> 10);
{
die(“You have submitted to many times”);
}
}

If you notice, ,on this script, I have 2 different error messages, one being too many and You have submitted to many times. When I am writing multiple scripts like this, I like to change the error message because it helps if you need to go in and debug the code. Again though, I would change it to something like “Page not Found” and not a “I caught you trying to attack me” type statement.

A couple of final words on this tutorial and security.

  • Always check your form with every new security measure you install, you may find that you form is getting stopped when you don’t want it to be. You may find that some of your data that you want sent to you is being blocked by your new scripts. So check them on several browsers and computers.
  • This is not the end all on security. Spammers and attackers are full time positions by very trained people that spend all day thinking of new ways to break a security measure. You should stay up on the latest security tactics and if they fit for you, adapt them.
  • You should also do a search for anti-spam scripts for that can purchased or can be downloaded for free. Its a good idea to look some of them over and see if any fit your needs. This is a good choice if you are planning on having a database that would hold information that is critical to your business or clients business.