Skip to content

Commit

Permalink
Added user_agent and remote_addr checks based on jas- proposition (#1).
Browse files Browse the repository at this point in the history
These checks are optionnal and can be activated using NoCSRF::enableOriginCheck(); before using the class.

Signed-off-by: Thibaut Despoulain <[email protected]>
  • Loading branch information
BKcore committed Dec 28, 2011
1 parent c43d0b1 commit 348c8b1
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
24 changes: 23 additions & 1 deletion example/nocsrf.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
*/
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.
Expand All @@ -19,6 +22,7 @@ class NoCSRF
* @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 )
Expand All @@ -41,6 +45,15 @@ public static function check( $key, $origin, $throwException=false, $timespan=nu
// 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 )
Expand All @@ -59,6 +72,14 @@ public static function check( $key, $origin, $throwException=false, $timespan=nu
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.
*
Expand All @@ -67,8 +88,9 @@ public static function check( $key, $origin, $throwException=false, $timespan=nu
*/
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() . self::randomString( 32 ) );
$token = base64_encode( time() . $extra . self::randomString( 32 ) );
// store the one-time token in session
$_SESSION[ 'csrf_' . $key ] = $token;

Expand Down
24 changes: 23 additions & 1 deletion nocsrf.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
*/
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.
Expand All @@ -19,6 +22,7 @@ class NoCSRF
* @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 )
Expand All @@ -41,6 +45,15 @@ public static function check( $key, $origin, $throwException=false, $timespan=nu
// 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 )
Expand All @@ -59,6 +72,14 @@ public static function check( $key, $origin, $throwException=false, $timespan=nu
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.
*
Expand All @@ -67,8 +88,9 @@ public static function check( $key, $origin, $throwException=false, $timespan=nu
*/
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() . self::randomString( 32 ) );
$token = base64_encode( time() . $extra . self::randomString( 32 ) );
// store the one-time token in session
$_SESSION[ 'csrf_' . $key ] = $token;

Expand Down

0 comments on commit 348c8b1

Please sign in to comment.