Protecting your CodeIgniter application from Cross-site request forgery (CSRF or XSRF) attacks is pretty easy thanks to the built-in support. Once CSRF protection is enabled in the config file, you can use the form helper or custom code to protect your forms and AJAX calls from CSRF. The CodeIgniter framework will automatically protect forms or calls that make POST requests once protection is enabled – here’s how to update your application.
Enable CSRF Protection
To enable CSRF protection in your CodeIgniter application, edit the application/config/config.php
file and look for $config['csrf_protection']
. Change the setting to TRUE
(if it isn’t already) to enable protection. If you then test a form or AJAX call in your application, the request will fail showing a generic error:
This means that CSRF protection is working, and we now need to update the forms to add a CSRF token to the POST data.
Updating forms with CSRF tokens
The easiest way to update your forms is to use the Form Helper. Load the form helper manually (in your controller) or add it to the application/config/autoload.php
file and call echo form_open('login');
(the first parameter is the form action
, and the second parameter is an array of attributes):
Using form_open()
will automatically add in a new field into the form with a randomly generated token used to prevent CSRF.
If you don’t want to use form_open()
, you can add it to your form manually with:
After updating your form, test the code by POSTing some data and the request should now go through as normal. To test it further, edit the value of the CSRF input (e.g. using Chrome), then submit the form again. Changing the CSRF token will result in the above error message as CodeIgniter has detected a CSRF attack.
Updating AJAX Calls
AJAX calls that POST data will also fail if the CSRF token is not added. CodeIgnitor will return a Error 500 (Internal Server Error)
for failed AJAX calls that do not contain a valid CSRF token field. There are a number of ways this can be achieved, depending on how you’ve coded your applications. I’ve included two different examples below:
Using JavaScript variables
Using Form Serialization
Once the changes have been made, test the AJAX call to see if the request is posted correctly and a valid response is received.
Thanks man
this a great post 🙂
Great Post
I’m using this framework but I have a problem to check the existence of this hidden field in my controlled I do something like this: if ($ this> input-> post (‘token’)): more code here endif; and that condition does not work, as if the field does not exist in reality but if it exists, I do sending $ (“# form”) serialize ().; or dudes = {‘token’: token} and nothing, any suggestions, maybe someone ah past. Thank you
Are you sure the data is being POSTed to your script using ajax?
try var_dump($this->input->post()) and check the index of the token, because it was set dynamically.
Thank a lot
Thanks for the information.
It helped me a lot!!!
Thanks…Great Post…
Thank you!
thanks but when use it show this warning
A PHP Error was encountered
Severity: Warning
Message: Illegal string offset ‘csrf_test_name’
Filename: helpers/form_helper.php
Line Number: 70
Sounds like your CSRF cookie name may be called something else. Check the
config.php
file and see what the value of$config['csrf_token_name']
is. Also, check that CSRF protection is enabled. This tutorial is quite old so the CodeIgnitor implementation for this could have also changed.Thanks for useful post. I follow your step, and it’s work in local host. I use jquery ui autocomplete to show data which i search and it work.
But when the project uploaded on online server, the console.log says “500(Internal Server Error)” when the word typed. And autocomplete was not work. I don’t know what happen. May be you can give an advice to solve my problem.
Thank’s, man
This sounds like a configuration issue with your server rather than a script issue. Make sure
mod_rewrite
/.htaccess
is configured correctly to allow routing to your controller, specifically, try visitingdata/header/lookup
in a browser and make sure it works.Thank’s mr. Niraj for your reply, i have fixed my problem. Before data sent using ajax, each value of get_csfr_token_name() method and get_csfr_hash() method must be setup with ajaxSetup() method then add it to ajax function then send. And it’s work well 🙂
But how do we add crsf data if we want to send more variables using ajax?
Thank’s before…
Added the CSRF variables to an array and then add any additional data your wish to send via Ajax. E.g.:
var data = { 'foo': 'bar', 'security->get_csrf_token_name(); ?>': 'security->get_csrf_hash();?>' };
What if there’s no form or ajax call at all? I have a delete button for objects that link to a delete method in it’s controller (e.g. /admin/article/delete/23). I can create params with token and hash, but how to check them in the controllers delete method?
With the delete button, it’s better to wrap your button with a Form and you can use the same code to validate the request. Optionally, you can add the CSRF token to the end of the delete button URL and validate it manually when clicked.
Superb tute.tx a lot .-Ujitha-
hi admin, whether CSRF value can be used to change parameter in address bar url? replace encrypt ci?
Sorry, not sure what you’re exactly asking?
can we use only csrf without AJAX calls?
and where we use AJAX calls ?
You can use csrf for both. However, for ajax calls, you’ll need to pass the token in your data / form and validate in a similar way to form data.
Can use both. When enabled in config its added by default to every form and checked on submit. When you want to use in AJAX or -in my case- delete urls, just add to the url as an url param and check it in the controller.
Add to url’s with (controller):
$this->data['token_hash'] = $this->security->get_csrf_hash();
And (view):
$url = 'admin/item/delete/' . $question->id . '?h='.$token_hash;
Check in controller:
if ( $_GET['h'] != $this->session->userdata('token_hash') ) {
$this->session->set_flashdata('notif', array('class'=>'error', 'message'=>'Question was not deleted due to security error'));
redirect('admin/faq/?page='.$this->input->get('page'));
}
$this->session->unset_userdata('token_hash');
It works if it is a single row.
From the next line, a 403 error occurs.
Cause and Countermeasure?
Thanks
You need to be more specific. Which part of the code works as a single line?