Created
March 12, 2013 20:32
-
-
Save meghuizen/5146751 to your computer and use it in GitHub Desktop.
Anti CSRF
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
<?php | |
/** | |
* See for more info: http://blog.ircmaxell.com/2013/02/preventing-csrf-attacks.html | |
*/ | |
abstract class CsrfToken { | |
private static $_currentToken; | |
private static $_tokenLifetime = 3600; // could be a nice addition | |
// could be $_SESSION['csrf_store'] for instance | |
private static $_csrfStore = array(); | |
public static function generateToken() { | |
$generator = (new \RandomLib\Factory())->getMediumStrengthGenerator(); | |
self::$_currentToken = array( | |
"key" => $generator->generateString($generator->generateInt(15, 25)), | |
"value" => $generator->generateString($generator->generateInt(40, 64)) | |
); | |
self::$_csrfStore[self::$_currentToken["key"]] = self::$_currentToken["value"]; | |
} | |
public static function getToken() { | |
if (empty(self::$_currentToken)) | |
self::generateToken(); | |
return self::$_currentToken; | |
} | |
public static function validate($inputarr) { | |
if (empty(self::$_csrfStore)) | |
return FALSE; | |
if (empty($inputarr) || !is_array($inputarr)) | |
return FALSE; | |
foreach ($inputarr as $key => $token) { | |
if (isset(self::$_csrfStore[$key]) && self::$_csrfStore[$key] === $token) { | |
// only allow 1 validation | |
// multiple validations in a single page load, should be done once and added to a global variable | |
unset(self::$_csrfStore[$key]); | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
public static function bindKeyStore(& $store) { | |
self::$_csrfStore = & $store; | |
if (empty(self::$_csrfStore)) | |
self::$_csrfStore = array(); | |
} | |
public static function setKeyStore($store) { | |
self::$_csrfStore = $store; | |
if (empty(self::$_csrfStore)) | |
self::$_csrfStore = array(); | |
} | |
public static function getKeyStore() { | |
return self::$_csrfStore; | |
} | |
} | |
/** RUNNING CODE **/ | |
// configuration | |
if (empty($_SESSION['csrf_store'])) | |
$_SESSION['csrf_store'] = array(); | |
// attach $_SESSION['csrf_store'] as CSRF store | |
CsrfToken::bindKeyStore($_SESSION['csrf_store']); | |
$token = CsrfToken::getToken(); | |
// on POST | |
if (!empty($_POST)) { | |
// validation code | |
$valid = CsrfToken::validate($_POST); | |
if (!$valid) { | |
// attack detected! FAIL! | |
die("Attack detected!"); | |
} | |
} | |
echo sprintf('<input type="hidden" name="%s" value=%s" />', | |
htmlentities($token["key"], ENT_QUOTES, 'UTF-8'), | |
htmlentities($token["value"], ENT_QUOTES, 'UTF-8') | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment