Skip to content

Instantly share code, notes, and snippets.

@meghuizen
Created March 12, 2013 20:32
Show Gist options
  • Save meghuizen/5146751 to your computer and use it in GitHub Desktop.
Save meghuizen/5146751 to your computer and use it in GitHub Desktop.
Anti CSRF
<?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