Created
January 6, 2014 07:07
-
-
Save CMCDragonkai/8279280 to your computer and use it in GitHub Desktop.
PHP: Codeigniter CSRF functionality does not support putting the CSRF token in the HTTP headers for the purposes of the double submit cookie method. It also only runs the CSRF check on POST and not on PUT or DELETE. This drop in MY_Security.php makes sure CSRF runs on POST, PUT or DELETE and checks the HTTP headers for X-XSRF-TOKEN recommended b…
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 | |
class MY_Security extends CI_Security{ | |
//overriding the normal csrf_verify, this gets automatically called in the Input library's constructor | |
//verifying on POST and PUT and DELETE | |
public function csrf_verify(){ | |
$request_method = strtoupper($_SERVER['REQUEST_METHOD']); | |
//If it is GET, ignore the rest | |
if($request_method == 'GET' OR $request_method == 'HEAD' OR $request_method == 'OPTIONS'){ | |
return $this->csrf_set_cookie(); | |
} | |
// Check if URI has been whitelisted from CSRF checks | |
if($exclude_uris = config_item('csrf_exclude_uris')){ | |
$uri = load_class('URI', 'core'); | |
if(in_array($uri->uri_string(), $exclude_uris)){ | |
return $this; | |
} | |
} | |
//Double submit cookie method: COOKIE needs to exist and at least either POST or SERVER needs to exist and at least one of the POST or SERVER must match the COOKIE | |
if( | |
!isset($_COOKIE[$this->_csrf_cookie_name]) | |
OR | |
( | |
!isset($_POST[$this->_csrf_cookie_name]) | |
AND | |
!isset($_SERVER['HTTP_X_XSRF_TOKEN']) | |
) | |
){ | |
$this->csrf_show_error(); | |
} | |
//if CSRF token was in the POST, then it needs to match the cookie | |
if(isset($_POST[$this->_csrf_token_name])){ | |
if($_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]){ | |
$this->csrf_show_error(); | |
} | |
} | |
//if CSRF token was in the SERVER (headers), then it needs to match the cookie | |
if(isset($_SERVER['HTTP_X_XSRF_TOKEN'])){ | |
if($_SERVER['HTTP_X_XSRF_TOKEN'] !== $_COOKIE[$this->_csrf_cookie_name]){ | |
$this->csrf_show_error(); | |
} | |
} | |
// We kill this since we're done and we don't want to polute the _POST array | |
unset($_POST[$this->_csrf_token_name]); | |
if(config_item('csrf_regenerate')){ | |
unset($_COOKIE[$this->_csrf_cookie_name]); | |
$this->_csrf_hash = ''; | |
} | |
$this->_csrf_set_hash(); | |
$this->csrf_set_cookie(); | |
log_message('debug', 'CSRF token verified'); | |
return $this; | |
} | |
} |
Edit: This is because Nginx apparently doesn't support this function. See the comments on http://php.net/manual/en/function.getallheaders.php for a solution.
@MohannadNaj
I get this error when I implement your code:
Fatal error: Uncaught Error: Class 'CI_Controller' not found in /projects/ditto/www/system/core/CodeIgniter.php:366 | |
Stack trace: | |
#0 /projects/ditto/www/system/core/Common.php(462): get_instance() | |
#1 /projects/ditto/www/system/core/Exceptions.php(105): log_message('error', 'Severity: error...') | |
#2 /projects/ditto/www/system/core/Common.php(727): CI_Exceptions->log_exception('error', 'Exception: Call...', '/projects/ditto...', 6) | |
#3 [internal function]: _exception_handler(Object(Error)) | |
#4 {main} | |
thrown in /projects/ditto/www/system/core/CodeIgniter.php on line 366 |
|
Fatal error: Uncaught Error: Class 'CI_Controller' not found in /projects/ditto/www/system/core/CodeIgniter.php:366 | |
Stack trace: | |
#0 /projects/ditto/www/system/core/Common.php(462): get_instance() | |
#1 /projects/ditto/www/system/core/Exceptions.php(105): log_message('error', 'Severity: Error...') | |
#2 /projects/ditto/www/system/core/Common.php(690): CI_Exceptions->log_exception('Error', 'Uncaught Error:...', '/projects/ditto...', 366) | |
#3 /projects/ditto/www/system/core/Common.php(766): _error_handler(1, 'Uncaught Error:...', '/projects/ditto...', 366) | |
#4 [internal function]: _shutdown_handler() | |
#5 {main} | |
thrown in /projects/ditto/www/system/core/CodeIgniter.php on line 366 |
|
Any idea what it could be?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm not working in codeigniter anymore, so if anyone has updates to it, feel free to post it and I'll update the gist.