Skip to content

Commit

Permalink
First commit.
Browse files Browse the repository at this point in the history
Signed-off-by: Thibaut Despoulain <[email protected]>
  • Loading branch information
BKcore committed Oct 25, 2011
0 parents commit 3a19cf7
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.md
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>
44 changes: 44 additions & 0 deletions example/example.php
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>
94 changes: 94 additions & 0 deletions example/nocsrf.php
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;
}

}
?>
94 changes: 94 additions & 0 deletions nocsrf.php
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;
}

}
?>

0 comments on commit 3a19cf7

Please sign in to comment.