Improving the Security of Your Website's Forms

« posted: September 11, 2010, 07:58:37 PM »

 
About Your PHP Forms

The PHP web forms in the SfS high schools reunion template provide a convenient way for your classmates to communicate with you and each other. They also give your website a more professional and polished appearance. PHP forms are inherently more secure than the older Perl-based CGI types, but unfortunately they are not immune from attempted exploitation by hackers. Their usual goals are two: (1) to simply submit links to their website(s) for the purpose of achieving better positioning in search results, or (2) to exploit your ISP's email server to transmit their marketing spam. In either case, they are usually either running a scam, or marketing sexually-oriented products or materials that you ordinarily would not wish to have your name associated with. In the worst case, the unsolicited email generated by a careless or inept attacker will show you as the sender, which can result in your receiving lots of angry responses, and your domain being added to a black list.

The purpose of this article is to help you modify your forms slightly, in order to provide some new protections from such exploitation.

So What's Up With This?

Your forms use "php" technology ("Hypertext Preprocessor"), which is a scripting language interpreted at the web server, rather than on the browser side of the connection, where it would be easily available to hackers. The forms do nothing but send field entries to a file on the web server, which contains another php script which knows what to do with that information. Since the scripting code on the web server is not easily available to outsiders, the process is ordinarily protected from easy exploits. However, dedicated hackers who are skilled in the use of PHP can figure out how to send code with your form which your server-side scrip will not recognize as illegitimate, and will therefore process without complaint. You can harden up your forms in order to frustrate such attacks by implementing a few simple changes:

These provisions ordinarily frustrate any attempt at automated hacking, and the presence of the CAPTCHA function ordinarily discourages manual attempts. Nevertheless, you will occasionally receive email containing links to other websites (amateurish attempts to exploit search engines), or strange code-like entries (amateurish attempts to crack your mail-server's security.) Your receipt of such messages can be considered a verification that the attempts failed, and they can simply be deleted without further ado.

Defeating Kainotophobia

If you have your PHP web forms up and running, you are probably not eager to start tinkering with them. Scripting systems are temperamental — a missing quotation mark here or an extra comma there and they'll crash, sending back some sort of cryptic complaint about an error, which only the most experienced might understand. And if you're not skilled in the scripting language, but are just trying to insert come cookie-cutter code into your website, the whole thing can quickly become impossibly frustrating.

Here's how you can avoid getting yourself in over your head in deep water:

Getting Started ... with "newsfrmack.php"

Step 1: Your existing "News Acknowledgement" probably has code that looks like this (except for the customizations you've already made, showing your own email address and domain name):

<?php
$email = $HTTP_POST_VARS[email];
$mailto = "webdev@ghhs58.org";
$mailsubj = "GHHS58.Org News Form Submission";
$mailhead = "From: $email\n";
reset ($HTTP_POST_VARS);
$mailbody = "Values submitted from web site form:\n";
while (list ($key, $val) = each ($HTTP_POST_VARS)) { $mailbody .= "$key : $val\n"; }
if (!eregi("\n",$HTTP_POST_VARS[email])) { mail($mailto, $mailsubj, $mailbody, $mailhead); }
?>

As the first step, replace $mailto in the last line to the email address used in the $mailto variable on the third line. Enclose it with single quote marks, and be careful about the comma. Then delete the $mailto line. Your script should now look like this.

<?php
$email = $HTTP_POST_VARS[email];
$mailto = "webdev@ghhs58.org";
$mailsubj = "GHHS58.Org News Form Submission";
$mailhead = "From: $email\n";
reset ($HTTP_POST_VARS);
$mailbody = "Values submitted from web site form:\n";
while (list ($key, $val) = each ($HTTP_POST_VARS)) { $mailbody .= "$key : $val\n"; }
if (!eregi("\n",$HTTP_POST_VARS[email])) { mail('webdev@ghhs58.org', $mailsubj, $mailbody, $mailhead); }
?>

Upload this modified page to your web server and submit a news form to ensure that it still works, and that the expected email response is received. If not, carefully recheck the changes you just made, and correct the error.

Step 2: Next, we'll be adding the CAPTCHA service, and after that the script will generate its own reply messages: "Received with thanks" if the CAPTCHA code was properly entered; otherwise "Please try again." For those messages will appear in the right place on the page, we'll need to move the script. It'll replace the existing message, which now probably looks something like this:

<td valign="top">
  <p class="book18bold" style="margin-left:5%;margin-right:10%;">News Acknowledgement</p>
  <p class="gray10" style="margin-left:10%;margin-right:10%;">Thank you. Your news submission was received. The webmaster will post it promptly.</p>
  <img src="../images/onepix.gif" width="1" height="107" title=""><br>
</td>

Delete the existing 'thank you ...' line, and move to whole script to within that <p></p> block. The results should look like this:

<td valign="top">
  <p class="book18bold" style="margin-left:5%;margin-right:10%;">News Acknowledgement</p>
  <p class="gray10" style="margin-left:10%;margin-right:10%;">Thank you. Your news submission was received. The webmaster will post it promptly.
<?php
$email = $HTTP_POST_VARS[email];
$mailto = "webdev@ghhs58.org";
$mailsubj = "GHHS58.Org News Form Submission";
$mailhead = "From: $email\n";
reset ($HTTP_POST_VARS);
$mailbody = "Values submitted from web site form:\n";
while (list ($key, $val) = each ($HTTP_POST_VARS)) { $mailbody .= "$key : $val\n"; }
if (!eregi("\n",$HTTP_POST_VARS[email])) { mail('webdev@ghhs58.org', $mailsubj, $mailbody, $mailhead); }
?>
  </p>
  <img src="../images/onepix.gif" width="1" height="107" title=""><br>
</td>

Upload your page again, and submit a news form to check it out. Note that there will be no message on the acknowledgement returned, because we haven't created that code yet, but you will receive the email response (one, and only one.) If necessary, recheck the changes you just made, and correct and problems.

Step 3: In this step we'll add a line of code that will look for unwanted content in submissions received for the form. Then we'll modify another line, adding code that will discard any such content. At the moment, your scrip looks like this:

<?php
$email = $HTTP_POST_VARS[email];
$mailsubj = "GHHS58.Org News Form Submission";
$mailhead = "From: $email\n";
reset ($HTTP_POST_VARS);
$mailbody = "Values submitted from web site form:\n";
while (list ($key, $val) = each ($HTTP_POST_VARS)) { $mailbody .= "$key : $val\n"; }
if (!eregi("\n",$HTTP_POST_VARS[email])) { mail('webdev@ghhs58.org', $mailsubj, $mailbody, $mailhead); }
?>

Add this line ... $find = array("/bcc\:/i","/Content\-Type\:/i","/cc\:/i","/to\:/i"); ... at the very top. Then copy and paste this line ... $email = preg_replace($find, '', $_POST['email']); over the existing $email line. The result should look exactly link this:

<?php
$find = array("/bcc\:/i","/Content\-Type\:/i","/cc\:/i","/to\:/i");
$email = preg_replace($find, '', $_POST['email']);

$mailsubj = "GHHS58.Org News Form Submission";
$mailhead = "From: $email\n";
reset ($HTTP_POST_VARS);
$mailbody = "Values submitted from web site form:\n";
while (list ($key, $val) = each ($HTTP_POST_VARS)) { $mailbody .= "$key : $val\n"; }
if (!eregi("\n",$HTTP_POST_VARS[email])) { mail('webdev@ghhs58.org', $mailsubj, $mailbody, $mailhead); }
?>

Again, upload this version of the page and submit "news" to ensure everything is still working as expected

Step 4: Finally, we'll add the lines that implement the CAPTCHA service.

Insert this short line ... <?session_start();?> at the very top of the page. Here's what the top of your page should then look like:

<?session_start();?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
... etc.

Upload the page again and check this out. If after adding this line the server returns an error message, recheck your work. If you've done everything correctly, and the form remains broken, the problem will be in the server's PHP setup, so email your hosting service (e.g., "support@seanic.net") and explain the problem. (Sometimes servers return just a warning, while actually processing the form correctly. Nevertheless, you don't want your visitors to be subjected to that, so do ask your support people for help in removing it.)

Now add these lines at the top of your script ...

if(($_SESSION['security_code'] == $_POST['security_code']) && (!empty($_SESSION['security_code'])) ) {
// CAPTCHA check successful. Insert your code for processing the form here.
$firstname = $_POST['firstname'];
echo 'Thank you '.$firstname.'. Your news item was received.';

... and add these lines at the very bottom ...

} else {
// Insert your code for showing an error message here
echo 'Sorry '.$firstname.', the security codes did not match.
Please use your browser back arrow and try again.';
}

Be careful about the braces in this code (also called "curly brackets" — "{" and "}".) They have a special significance, and cannot be omitted or replaced by parenthesis. Your finished script should look like this, except, of course, it will have your email address and domain name;

<?php
if(($_SESSION['security_code'] == $_POST['security_code']) && (!empty($_SESSION['security_code'])) ) {
// CAPTCHA check successful. Insert your code for processing the form here.
$firstname = $_POST['firstname'];
echo 'Thank you '.$firstname.'. Your news item was received.';

$find = array("/bcc\:/i","/Content\-Type\:/i","/cc\:/i","/to\:/i");
$email = preg_replace($find, '', $_POST['email']);
$mailsubj = "GHHS58.Org News Form Submission";
$mailhead = "From: $email\n";
reset ($HTTP_POST_VARS);
$mailbody = "Values submitted from web site form:\n";
while (list ($key, $val) = each ($HTTP_POST_VARS)) { $mailbody .= "$key : $val\n"; }
if (!eregi("\n",$HTTP_POST_VARS[email])) { mail('webdev@ghhs58.org', $mailsubj, $mailbody, $mailhead); }
} else {
// Insert your code for showing an error message here
echo 'Sorry '.$firstname.', the security codes did not match. Please use your browser back arrow and try again.';
}

?>

Upload your page and check it out. If everything is working correctly, you'll receive the "Sorry ..." message, since we have yet to implement the CAPTCHA system on the form itself. Since the submission was blocked, you will not be receiving any email from this submission either.

Congratulations! You've successfully modified your news submission acknowledgement page.

Next task ... "newsfrm.html"

The form on your news submission page needs only two simple changes.

You might have noticed that the "Sorry ..." message returned above did not include your name, as you might have expected had you been paying close attention to the code in the script. Your first name was not included, because the original form didn't provide separate first name and last name fields. Including the first name in the echoed responses personalizes the transactions somewhat, so is a nice touch. To implement that, we'll add a first name field to the form. Then we'll add a space for the CAPTCHA image, and a field that will permit people to respond to the query by typing in the characters they see in the image.

Step 5: You can probably figure out how to modify the name fields in your form by simply looking at it.

<form method="POST" action="newsack.php">
Name: <input class="black7" type="TEXT" name="name"><br>
<span style="font-size:1pt;"> </span><br>
Email: <input class="black7" type="TEXT" name="email"><br>
 <br>
Comments:<img src="../images/onepix.gif" width="240" height="1" alt=""><br>
<textarea class="gray7" name="Comments" cols="55" rows="4"></textarea><br>
 <br>
<input class="button7" type="SUBMIT" name="Submit" value=" Submit " title="Submit your news electronically.">
/form>

Simply highlight and copy the existing "Name;" line and the spacer line under it to the clipboard, the paste the clipboard over these highlighted lines twice. Then revise the legends next to these inputs, and change the "name" attributes within their respective "input" tags, using the names shown — "firstname" and "lastname":

<form method="POST" action="newsack.php">
First Name: <input class="black7" type="TEXT" name="firstname"><br>
<span style="font-size:1pt;"> </span><br>
Last Name: <input class="black7" type="TEXT" name="lastname"><br>
<span style="font-size:1pt;"> </span><br>

Email: <input class="black7" type="TEXT" name="email"><br>
&nbsp;<br>
Comments:<img src="../images/onepix.gif" width="240" height="1" alt=""><br>
<textarea class="gray7" name="Comments" cols="55" rows="4"></textarea><br>
&nbsp;<br>
<input class="button7" type="SUBMIT" name="Submit" value=" Submit " title="Submit your news electronically.">
/form>

Upload your modified page to the web server, refresh the page in your browser and submit a test news item. If this all worked our right, you'll now see your name in the "Sorry ..." message.

Now you need to add three lines to the form, just above the "SUBMIT" line at the bottom. Add these two lines:

<img src="CaptchaSecurityImages.php" />
Security Code: <input id="security_code" name="security_code" type="text" />
&nbsp;<br>

The first line calls upon the CAPTCHA service to send a code in the form of and image, and the second line provides a space for the visitor to enter the code they see into the form. The form will now look like this;

<form method="POST" action="newsack.php">
First Name: <input class="black7" type="TEXT" name="firstname"><br>
<span style="font-size:1pt;"> </span><br>
Last Name: <input class="black7" type="TEXT" name="lastname"><br>
<span style="font-size:1pt;"> </span><br>
Email: <input class="black7" type="TEXT" name="email"><br>
&nbsp;<br>
Comments:<img src="../images/onepix.gif" width="240" height="1" alt=""><br>
<textarea class="gray7" name="Comments" cols="55" rows="4"></textarea><br>
&nbsp;<br>
<img src="CaptchaSecurityImages.php" />
Security Code: <input id="security_code" name="security_code" type="text" />
&nbsp;<br>

<input class="button7" type="SUBMIT" name="Submit" value=" Submit " title="Submit your news electronically.">
/form>

Step 6: Before you will be able to successfully test your "newsfrm.html" page again, you will need to get the "CaptchaSecurityImages.php" script and a copy of the font it uses, and install these in the same folder as your news form. You can download the latest version of "CAPTCHA.zip" from its British creators, White Hat Web Development, or from here. Within the zip package you will find ...

Put these two files in the local folder containing "newsfrm.html."

You are now ready to test your news submission form. Upload all three files ... "newsfrm.html", "CaptchaSecurityImages.php" and "monofont.ttf" to your web server, all to the same folder. Open your news submission form in your browser (be sure to refresh the page) and you should see the CAPTCHA image and input field appear. Fill in the form, enter the characters you see in the image in the "Security Code" box, and click the "Submit" button. If everything works out, you'll receive the "Thank you ..." message.

Wonderful! You now successfully created a highly secure web form.

Updating Your Other Forms

Other areas of your website that include forms are these ...

Having succeeded in hardening up your "News" form, you can confidently apply the same changes to your other forms. Here's how:

Step 7: All of the acknowledgement scripts are the same, except for the wording of the "echo" strings. So copy the script from your "newsfrmack.php" file into the appropriate place in these other files, as explained above in "Step 2" ...

Open each one of these files and revise the CAPTCHA response strings, and the subject line in the $mailsubj variable as needed.

Refer to "Step 4" above, and add the <?session_start();?> line at the top of each page. Finally, delete the original block of PHP script.

Step 8: All of the original forms used a single "full name" field, so the instructions provided above for the "newsfrm.html" (Step 6) can be repeated exactly for these form:

Change the "name" field to a "firstname" field, then copy and paste that to add a "lastname" field. A small exception is "classmatesfrm.html" on which the first field is "originalname" ("Your Original Full Name:"). Treat that in the same way, renaming the fields "firstname" ("Your Original First Name:") and "lastname" ("Your Original Last Name:").

Then add the three lines for the CAPTCHA service above the "SUBMIT" button.

Step 9: Each one of these folder must have a local copy of "CaptchaSecurityImages.php" and "monofont.ttf". Copy these two files from your "news" folder to these folders:

You can then upload this updated material to your web server, and test each new form. For each folder, you will be uploading four items:

Al Finished! Your website is now hacker-unfriendly.

Conclusion

Your web forms are now much more difficult for a hacker to exploit. You're not likely to be bothered much by experienced hackers, since they know there are lots of easy targets available, so they'll not need to waste their time with yours. As mentioned above, you'll still occasionally receive bogus submissions from novices who don't yet know enough to understand that they're wasting their time. You can simply delete those upon receipt, being confident that they didn't go anywhere except to your own inbox.

We hope you have enjoyed this challenging exercise, and are feeling proud of having accomplished a "job well done." Thanks for using the SfS Class Reunion Website Template

Close