Click to See Complete Forum and Search --> : [RESOLVED] Avoid "refresh" form submissions and some 'bots


NogDog
05-03-2008, 04:18 PM
Based on recent discussions in other threads, I thought up this technique to prevent 'bot submissions that directly call the page (instead of first requesting the form page) and also prevents repeat form submissions via the browser refresh function. Just curious if anyone sees any possible problems with this, or any useful enhancements.

<?php
session_start();
$errors = array();
$result = null;
// handle form submissions
if(isset($_POST['test']))
{
// make sure the hidden field value matches the session value:
if(empty($_POST['nogdog'])
or empty($_SESSION['nogdog'])
or $_POST['nogdog'] != $_SESSION['nogdog'])
{
$errors[] = "Either this was a duplicate submission, your browser " .
"does not support cookies, or you are a robot script " .
"trying to spam me.";
}
// go ahead and process the form
else
{
$result = trim($_POST['test']);
}
}
// set a new random value for the session and hidden field values:
$nogdog = uniqid();
$_SESSION['nogdog'] = $nogdog;
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>Test Form</title>
</head>
<body>
<form action="<?php
echo $_SERVER['SCRIPT_NAME'];
?>" method="post">
<fieldset>
<legend>test</legend>
<input type="text" name="test" size="20" maxlength="20">
<input type="submit" value="Submit">
<input type="hidden" name="nogdog" value="<?php
echo $nogdog;
?>">
</fieldset>
</form>
<?php
// show results:
if(!empty($errors))
{
foreach($errors as $err)
{
echo "<p class='error'>$err</p>\n";
}
}
if(!empty($result))
{
echo "<p>You entered: '".htmlentities($result)."'</p>\n";
}
?>
</body>
</html>

Shrike
05-05-2008, 06:24 AM
Not sure if you realise or not NogDog, but this technique also prevents cross-site request forgery attacks. The atack works as follows:

- User logs in to www.legitimate-site.com
- User is lured to www.evil-site.com (phishing or some other method)
- www.evil-site.com does a header redirect or something similar to www.legitimate-site.com
- Since User still has a valid session ID, the request is allowed through
- www.evil-site.com gains some confidential info

With your method the additional token from uniqid() prevents the blind acceptance of a valid session ID. Nice :)

Horizon88
05-05-2008, 02:28 PM
I used this technique in a security reporting system here at work, once - token systems are pretty useful. Looks good. :D

NogDog
05-05-2008, 03:55 PM
Thanks for the feedback, guys. It seemed a little "too easy", making me wonder if I was missing something stupid. I'm going to mark this resolved, but if anyone sees any problems with it, don't hesitate to chime in.

Horizon88
05-05-2008, 10:21 PM
http://php.robm.me.uk/#toc-CSRF covers it a bit, too, if you wanted to see the way he does it.