-
-
Save CMCDragonkai/8279280 to your computer and use it in GitHub Desktop.
<?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; | |
} | |
} |
This is awesome. Thank you so much for taking the time to create it. This should absolutely be pushed to the 3.0 branch.
This looks great... I just can't get it to work. I've placed MY_Security in the application/core
folder and I'm sending HTTP_X_XSRF_TOKEN
with the token, which matches the CSFR cookie, but I'm still getting The action you have requested is not allowed.
Any ideas?
Thanks for this!
for the purpose of only make codeigniter recognize csrf in Headers, can anyone illuminate me why this simple override is not enough:
<?php
class MY_Security extends CI_Security{
public function csrf_verify()
{
$headers = getallheaders();
if(isset($headers[$this->_csrf_token_name])) {
$_POST[$this->_csrf_token_name] = $headers[$this->_csrf_token_name];
}
parent::csrf_verify();
}
}
I tried some tests and it's working well, but since I'm not expert enough I hope someone light me up on this. thanks.
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.
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?
Unbelievable! I was just thinking about the same CI modification as You have made here! I cannot believe that nobody cares about CI CSRF protection of PUT and DELETE. With your kind permission I will use this code in my app.
Just wondering about the URI whitelist - is it your idea or it is in CI 3.0? Can you give me an example where to use it?
Thank you