-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Thibaut Despoulain <[email protected]>
- Loading branch information
0 parents
commit 3a19cf7
Showing
4 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#NoCSRF, a simple PHP5 token class to prevent CSRF attacks. | ||
|
||
* [Website](http://bkcore.com/blog/code/nocsrf-php-class.html) | ||
* Author: Thibaut Despoulain | ||
* Version: 1.0 | ||
* Licensed under the MIT license <http://www.opensource.org/licenses/mit-license.php> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
session_start(); | ||
|
||
include('nocsrf.php'); | ||
|
||
if ( isset( $_POST[ 'field' ] ) ) | ||
{ | ||
try | ||
{ | ||
// Run CSRF check, on POST data, in exception mode, for 10 minutes | ||
NoCSRF::check( 'csrf_token', $_POST, true, 60*10 ); | ||
// form parsing, DB inserts, etc. | ||
// ... | ||
$result = 'CSRF check passed. Form parsed.'; | ||
} | ||
catch ( \Exception $e ) | ||
{ | ||
// CSRF attack detected | ||
$result = $e->getMessage() . ' Form ignored.'; | ||
} | ||
} | ||
else | ||
{ | ||
$result = 'No post data yet.'; | ||
} | ||
// Generate CSRF token to use in form hidden field | ||
$token = NoCSRF::generate( 'csrf_token' ); | ||
?> | ||
|
||
|
||
<h1>CSRF sandbox</h1> | ||
<pre style="color: red"><?php echo $result; ?></pre> | ||
<form name="csrf_form" action="#" method="post"> | ||
<h2>Form using generated token.</h2> | ||
<input type="hidden" name="csrf_token" value="<?php echo $token; ?>"> | ||
<input type="text" name="field" value="somevalue"> | ||
<input type="submit" value="Send form"> | ||
</form> | ||
<form name="nocsrf_form" action="#" method="post"> | ||
<h2>Copied form simulating CSRF attack.</h2> | ||
<input type="hidden" name="csrf_token" value="whateverkey"> | ||
<input type="text" name="field" value="somevalue"> | ||
<input type="submit" value="Send form"> | ||
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<?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 | ||
{ | ||
/** | ||
* 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) | ||
* @return Boolean Returns FALSE if a CSRF attack is detected, TRUE otherwise. | ||
*/ | ||
public static function check( $key, $origin, $throwException=false, $timespan=null ) | ||
{ | ||
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. | ||
$_SESSION[ 'csrf_' . $key ] = null; | ||
|
||
// 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; | ||
} | ||
|
||
/** | ||
* 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 ) | ||
{ | ||
// token generation (basically base64_encode any random complex string, time() is used for token expiration) | ||
$token = base64_encode( time() . 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; | ||
} | ||
|
||
} | ||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<?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 | ||
{ | ||
/** | ||
* 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) | ||
* @return Boolean Returns FALSE if a CSRF attack is detected, TRUE otherwise. | ||
*/ | ||
public static function check( $key, $origin, $throwException=false, $timespan=null ) | ||
{ | ||
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. | ||
$_SESSION[ 'csrf_' . $key ] = null; | ||
|
||
// 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; | ||
} | ||
|
||
/** | ||
* 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 ) | ||
{ | ||
// token generation (basically base64_encode any random complex string, time() is used for token expiration) | ||
$token = base64_encode( time() . 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; | ||
} | ||
|
||
} | ||
?> |