为什么这个脚本不会保护我的表单免受CSRF攻击?就像我试图添加他们在网站nocsrf网站上的演示形式,这是完美的。当我更改csrf令牌的代码时,没有任何事情发生,它只是将信息处理到我当前表单上的数据库。
这是我的 表单部分,它与html表单在同一页面上:
$editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
$editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}
if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
$insertSQL = sprintf("INSERT INTO contact (name, email, topic, `description`, IP, date) VALUES (%s, %s, %s, %s, %s, %s)",
GetSQLValueString($_POST['name'], "text"),
GetSQLValueString($_POST['email'], "text"),
GetSQLValueString($_POST['topic'], "text"),
GetSQLValueString($_POST['description'], "text"),
GetSQLValueString($_SERVER['REMOTE_ADDR'], "text"),
GetSQLValueString(date("Y-m-d H:i:s"), "text"));
mysql_select_db($database_config, $config);
$Result1 = mysql_query($insertSQL, $config) or die(mysql_error());
$insertGoTo = "takk.php";
if (isset($_SERVER['QUERY_STRING'])) {
$insertGoTo .= (strpos($insertGoTo, '?')) ? "&" : "?";
$insertGoTo .= $_SERVER['QUERY_STRING'];
}
header(sprintf("Location: %s", $insertGoTo));
}
这是我的html表单部分:
<form action="#" method="post" name="form1" id="form1">
<h4>Navn:</h4>
<input type="text" class="form-control" name="name" value="" size="32" required>
<h4>Email:</h4>
<input type="email" class="form-control" name="email" value="" size="32" required>
<h4>Kategori:</h4>
<select name="topic" class="form-control">
<option value="Generelt" <?php if (!(strcmp("Generelt", ""))) {echo "SELECTED";} ?>>Generelle spørsmål</option>
<option value="Problemer" <?php if (!(strcmp("Problemer", ""))) {echo "SELECTED";} ?>>Problemer</option>
<option value="Klage" <?php if (!(strcmp("Klage", ""))) {echo "SELECTED";} ?>>Klage</option>
<option value="Bugs" <?php if (!(strcmp("Bugs", ""))) {echo "SELECTED";} ?>>Bugs</option>
</select>
<h4>Hva lurer du på?</h4>
<textarea name="description" class="form-control" cols="50" rows="5" required></textarea>
<br />
<button type="submit" class="blue-button" style="width:100%;">Send henvendelse</button>
<input type="hidden" name="csrf_token" value="<?php echo $token; ?>">
<input type="hidden" name="MM_insert" value="form1" />
</form>
Nocsrf.php
<?php
/**
* NoCSRF, an anti CSRF token generation/checking class.
*
* Copyright (c) 2011 Thibaut Despoulain <http://bkcore.com/blog/code/nocsrf-php-class.html>
* Licensed under the MIT license <http://www.opensource.org/licenses/mit-license.php>
*
* @author Thibaut Despoulain <http://bkcore.com>
* @version 1.0
*/
class NoCSRF
{
protected static $doOriginCheck = false;
/**
* Check CSRF tokens match between session and $origin.
* Make sure you generated a token in the form before checking it.
*
* @param String $key The session and $origin key where to find the token.
* @param Mixed $origin The object/associative array to retreive the token data from (usually $_POST).
* @param Boolean $throwException (Facultative) TRUE to throw exception on check fail, FALSE or default to return false.
* @param Integer $timespan (Facultative) Makes the token expire after $timespan seconds. (null = never)
* @param Boolean $multiple (Facultative) Makes the token reusable and not one-time. (Useful for ajax-heavy requests).
*
* @return Boolean Returns FALSE if a CSRF attack is detected, TRUE otherwise.
*/
public static function check( $key, $origin, $throwException=false, $timespan=null, $multiple=false )
{
if ( !isset( $_SESSION[ 'csrf_' . $key ] ) )
if($throwException)
throw new Exception( 'Missing CSRF session token.' );
else
return false;
if ( !isset( $origin[ $key ] ) )
if($throwException)
throw new Exception( 'Missing CSRF form token.' );
else
return false;
// Get valid token from session
$hash = $_SESSION[ 'csrf_' . $key ];
// Free up session token for one-time CSRF token usage.
if(!$multiple)
$_SESSION[ 'csrf_' . $key ] = null;
// Origin checks
if( self::$doOriginCheck && sha1( $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) != substr( base64_decode( $hash ), 10, 40 ) )
{
if($throwException)
throw new Exception( 'Form origin does not match token origin.' );
else
return false;
}
// Check if session token matches form token
if ( $origin[ $key ] != $hash )
if($throwException)
throw new Exception( 'Invalid CSRF token.' );
else
return false;
// Check for token expiration
if ( $timespan != null && is_int( $timespan ) && intval( substr( base64_decode( $hash ), 0, 10 ) ) + $timespan < time() )
if($throwException)
throw new Exception( 'CSRF token has expired.' );
else
return false;
return true;
}
/**
* Adds extra useragent and remote_addr checks to CSRF protections.
*/
public static function enableOriginCheck()
{
self::$doOriginCheck = true;
}
/**
* CSRF token generation method. After generating the token, put it inside a hidden form field named $key.
*
* @param String $key The session key where the token will be stored. (Will also be the name of the hidden field name)
* @return String The generated, base64 encoded token.
*/
public static function generate( $key )
{
$extra = self::$doOriginCheck ? sha1( $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) : '';
// token generation (basically base64_encode any random complex string, time() is used for token expiration)
$token = base64_encode( time() . $extra . self::randomString( 32 ) );
// store the one-time token in session
$_SESSION[ 'csrf_' . $key ] = $token;
return $token;
}
/**
* Generates a random string of given $length.
*
* @param Integer $length The string length.
* @return String The randomly generated string.
*/
protected static function randomString( $length )
{
$seed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijqlmnopqrtsuvwxyz0123456789';
$max = strlen( $seed ) - 1;
$string = '';
for ( $i = 0; $i < $length; ++$i )
$string .= $seed{intval( mt_rand( 0.0, $max ) )};
return $string;
}
}
?>