Skip to content

Commit

Permalink
Merge pull request #88 from mebjas/dev-master-issue80
Browse files Browse the repository at this point in the history
Fix to issue #80
  • Loading branch information
mebjas authored Oct 6, 2017
2 parents 756129f + 5fda1dc commit 88cfff1
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 20 deletions.
12 changes: 2 additions & 10 deletions js/csrfprotector.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,16 +289,8 @@ function csrfprotector_init() {
*/
function new_send(data) {
if (this.method.toLowerCase() === 'post') {
if (data !== null && typeof data === 'object') {
data.append(CSRFP.CSRFP_TOKEN, CSRFP._getAuthKey());
} else {
if (typeof data != "undefined") {
data += "&";
} else {
data = "";
}
data += CSRFP.CSRFP_TOKEN +"=" +CSRFP._getAuthKey();
}
// attach the token in request header
this.setRequestHeader(CSRFP.CSRFP_TOKEN, CSRFP._getAuthKey());
}
return this.old_send(data);
}
Expand Down
55 changes: 47 additions & 8 deletions libs/csrf/csrfprotector.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?php

if (!defined('__CSRF_PROTECTOR__')) {
define('__CSRF_PROTECTOR__', true); // to avoid multiple declaration errors

Expand Down Expand Up @@ -90,10 +89,17 @@ class csrfProtector
/**
* Variable: $cookieConfig
* Array of parameters for the setcookie method
* @var cookieConfig;
* @var array<any>
*/
private static $cookieConfig = null;

/**
* Variable: $tokenHeaderKey
* Key value in header array, which contain the token
* @var string
*/
private static $tokenHeaderKey = null;

/*
* Variable: $requestType
* Varaible to store weather request type is post or get
Expand Down Expand Up @@ -188,6 +194,9 @@ public static function init($length = null, $action = null)
if (self::$config['CSRFP_TOKEN'] == '')
self::$config['CSRFP_TOKEN'] = CSRFP_TOKEN;

self::$tokenHeaderKey = 'HTTP_' .strtoupper(self::$config['CSRFP_TOKEN']);
self::$tokenHeaderKey = str_replace('-', '_', self::$tokenHeaderKey);

// load parameters for setcookie method
if (!isset(self::$config['cookieConfig']))
self::$config['cookieConfig'] = array();
Expand Down Expand Up @@ -248,19 +257,19 @@ public static function authorizePost()
//set request type to POST
self::$requestType = "POST";

// look for token in payload else from header
$token = self::getTokenFromRequest();

//currently for same origin only
if (!(isset($_POST[self::$config['CSRFP_TOKEN']])
&& isset($_SESSION[self::$config['CSRFP_TOKEN']])
&& (self::isValidToken($_POST[self::$config['CSRFP_TOKEN']]))
)) {
if (!($token && isset($_SESSION[self::$config['CSRFP_TOKEN']])
&& (self::isValidToken($token)))) {

//action in case of failed validation
self::failedValidationAction();
self::failedValidationAction();
} else {
self::refreshToken(); //refresh token for successfull validation
}
} else if (!static::isURLallowed()) {

//currently for same origin only
if (!(isset($_GET[self::$config['CSRFP_TOKEN']])
&& isset($_SESSION[self::$config['CSRFP_TOKEN']])
Expand All @@ -275,6 +284,36 @@ public static function authorizePost()
}
}

/*
* Fucntion: getTokenFromRequest
* function to get token in case of POST request
*
* Parameters:
* void
*
* Returns:
* any (string / bool) - token retrieved from header or form payload
*/
private static function getTokenFromRequest() {
// look for in $_POST, then header
if (isset($_POST[self::$config['CSRFP_TOKEN']])) {
return $_POST[self::$config['CSRFP_TOKEN']];
}

if (function_exists('apache_request_headers')) {
if (isset(apache_request_headers()[self::$config['CSRFP_TOKEN']])) {
return apache_request_headers()[self::$config['CSRFP_TOKEN']];
}
}

if (self::$tokenHeaderKey === null) return false;
if (isset($_SERVER[self::$tokenHeaderKey])) {
return $_SERVER[self::$tokenHeaderKey];
}

return false;
}

/*
* Function: isValidToken
* function to check the validity of token in session array
Expand Down
31 changes: 29 additions & 2 deletions test/csrfprotector_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,10 @@ public function testAuthorisePost_failedAction_6()
}

/**
* test authorise success
* test authorise success with token in $_POST
*/
public function testAuthorisePost_success()
{

$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST[csrfprotector::$config['CSRFP_TOKEN']]
= $_GET[csrfprotector::$config['CSRFP_TOKEN']]
Expand Down Expand Up @@ -382,6 +381,34 @@ public function testAuthorisePost_success()
// $this->assertTrue(csrfp_wrapper::checkHeader($_SESSION[csrfprotector::$config['CSRFP_TOKEN']][0])); // Combine these 3 later
}

/**
* test authorise success with token in header
*/
public function testAuthorisePost_success_2()
{
unset($_POST[csrfprotector::$config['CSRFP_TOKEN']]);
$_SERVER['REQUEST_METHOD'] = 'POST';
$serverKey = 'HTTP_' .strtoupper(csrfprotector::$config['CSRFP_TOKEN']);
$serverKey = str_replace('-', '_', $serverKey);

$csrfp = new csrfProtector;
$reflection = new \ReflectionClass(get_class($csrfp));
$property = $reflection->getProperty('tokenHeaderKey');
$property->setAccessible(true);
// change value to false
$property->setValue($csrfp, $serverKey);

$_SERVER[$serverKey] = $_SESSION[csrfprotector::$config['CSRFP_TOKEN']][0];
$temp = $_SESSION[csrfprotector::$config['CSRFP_TOKEN']];

csrfprotector::authorizePost(); //will create new session and cookies
$this->assertFalse($temp == $_SESSION[csrfprotector::$config['CSRFP_TOKEN']][0]);
$this->assertTrue(csrfp_wrapper::checkHeader('Set-Cookie'));
$this->assertTrue(csrfp_wrapper::checkHeader('csrfp_token'));
// $this->assertTrue(csrfp_wrapper::checkHeader($_SESSION[csrfprotector::$config['CSRFP_TOKEN']][0])); // Combine these 3 later

}

/**
* test for generateAuthToken()
*/
Expand Down

0 comments on commit 88cfff1

Please sign in to comment.