Page 1 of 1

Anti-CSRF code giving unexpected results.

Posted: Wed Dec 06, 2006 10:25 am
by impulse()
I've been polishing up my security with forms today and I've come across a chapter which shows me how to avoid CSRF attacks. I've learned to use the following code to avoid these attacks but I'm getting unexpected results. Please can somebody point out why on each form submittion the results of the 2 variables never match:

Code: Select all

session_start();

$_SESSION['token'] = md5(uniqid(rand(), TRUE));

echo "<form method = 'post' action = 'uni.php'>";
echo "<input type = 'hidden' name = 'check' value = '$_SESSION[token]'>";
echo "<input type = 'text' name = 'one'>";
echo "<input type = 'submit' value = 'Submit'>";
echo "</form>";

if (isset($_POST['one'])) {
  if ($_SESSION['token'] == $_POST['check']) {
    echo "Match";
  }
}

echo $_POST['check'];
echo "<br>";
echo $_SESSION['token'];
$_POST['check'] and $_SESSION['token'] never match.

Regards, Stephen

Posted: Wed Dec 06, 2006 10:55 am
by volka
You're setting a new $_SESSION['token'] with each request, regardless of wether the form is displayed and/or the form values are processed.
This might be the result of a misconception on how php works. Try

Code: Select all

<?php session_start(); ?>
<html>
	<head><title>To illustrate why it does not works</title>
	<body>
<?php
$_SESSION['token'] = md5(uniqid(rand(), TRUE));
echo '<div>setting token to: ', $_SESSION['token'], "</div>\n";
echo '<div>_POST[check]: ', isset($_POST['check']) ? $_POST['check']:'-not set-', "</div>\n";

echo "<form method = 'post' action = '#'>";
echo "<input type = 'hidden' name = 'check' value = '$_SESSION[token]'>";
echo "<input type = 'text' name = 'one'>";
echo "<input type = 'submit' value = 'Submit'>";
echo "</form>";

if (isset($_POST['one'])) {
	if ($_SESSION['token'] == $_POST['check']) {
		echo "Match";
	}
	else {
		echo 'no match';
	}
}
else {
	echo '<div>_POST[one] not set</div>';
}
?>
	</body>
</html>