26
Jul

5 reasons to NOT use csrf_protection in Codeigniter

I just wanted to tell a small funny story as an introduction of the reasons why to not use csrf_protection in Codeigniter. If you though just want to read the reasons why, go straight away to 5 simple reasons for why not to use csrf_protection of Codeigniter…

For the other users just keep reading …

A small story first

You are using PHP Codegniter Framework and you are really happy about the tools that it offers to you.You have created a whole website in just few days and you are really proud of it. Last time there was an article about security in Codeigniter? With a quick google search you just found csrf_protection has to be set to true for hacks attacks. They also mentioned that you have to use form_open for your forms.

WOW! This is not a problem for you as you already use form_open and form_close for the set_rules. So really happy that your website is also secure now, you tweet it , you write it on facebook, you also tell it to your customer that the system now it is even more secure for future hack attacks…

and the problems just started… an unexpected error out of nowhere!!!

Next day, your customer called you angry and telling you about a weird error in his screen.

Then you realize that you cannot understand where the problem is. After lot of searching you realized that the csrf_protection doesn’t support AJAX forms. As always … google search and yes you finally find an article (eg. AJAX with CSRF Protection in Codeigniter 2.0) that tell you about the cookies and other stuff like this. You don’t really understand why it will work like this, so… you just copy the code to your project and TADA it works!

It’s been a while that your customer didn’t tell anything and everything seems to works fine. Then the same customer again realized that some users that using internet explorer (not the old one, the new IE9) they have the same error.

And then you realize that the csrf_protection has the problem. You also mentioned that even some forms in the backend system didn’t work properly but at least the customer didn’t know it, so that’s fine. So after 1 day researching you understood that you cannot find a solution for all the forms and you just set csrf_protection back to false as you didn’t understand at the first place what hack attacks you could prevent.

If this story sounds familiar with yours then I suggest to not use the default CSRF protection of Codeigniter. Why?

There are 5 simple reasons…

1. You don’t prevent hack attacks. Only some automated bots.

2. It works fine only for simple forms. It is unstable for AJAX forms.

3. It doesn’t work when the cookies are disabled.

4. There is a general error (The action you have requested is not allowed.) that a simple user cannot understand what is going on and neither the developer can understand where the problem is!

5. It is not IE 7 and Opera compatible for AJAX requests as far as I tested

I will not explain further my reasons as I think that I will have long discussions with people that don’t have the same opinion with me and this is not the point of this article. I will try to give some small solutions of what to do instead of setting csrf_protection to true.

Solutions?

I liked an article that I have read about crsf protection Protect a CodeIgniter Application Against CSRF . At the end of the article they say that:

Alternatively, as of CodeIgniter v2.0, protection against CSRF attacks is now built into the framework!

but I prefer to use this one as it use session rather than the $_COOKIE of Codeigniter default one. You can even understand the logic and create your own hook for csrf protection.

First of all let’s start of what is the Cross-Site Request Forgery protection and why you should protect your forms from attacks:

What is the CSRF protection?

An attacker could create a bogus form on his site – for example a search form. This form could have hidden inputs that contain malicious data. Now the form isn’t actually sent to the attacker’s site to perform the search; in reality, the form points to your site! Since your website will trust that the form is genuine, it goes through and executes the requested (and perhaps malicious) actions.

Imagine that a user is logged into your site, and is redirected to the attacker’s site for some reason (phishing, XSS, you name it). The attacker’s form could point to your account deletion form on your site. If the user performs a “search” on the attackers site, his account will then be deleted without him knowing!

For more read the full article here

Advices

Don’t expect to have just one line of code and have all the security that is needed. Even the most powerful PHP frameworks need time to improve the security. The knownledge of security is very important and it prevents you from long term problems. Also as many things you really know about security the better. So my advice is to read the article of Application Against CSRF or similar articles for form protections and learn what is going on and then create your own custom hook.

In my experience is more important to actually make things work rather than block every form with the risk of not sending the message to the admin or user and doesn’t even realize it.

So general advices for the forms to be more secure:

  • Log your forms. Just log all the requests of the forms in the database or in files.
  • Don’t name your admin controller admin or administrator.
  • Use a captcha authorisation for all your frontend forms unless the user is logged in.
  • Use your own custom security library for the forms to prevent attacks.
  • Don’t have dump passwords neither on testing mode. Passwords such as password,123456, admin, e.t.c. can cause big problems if you have by mistake a dump password on production mode without realizing it.
  • Always escape your input values and be careful to validate and trim any data that comes from the frontend website.
  • Always try to use tokens for your forms to check if the submit is coming from your site or not. For example a hidden input.



I think with those small security advices you can prevent the most hack attacks from the frontend website.

And don’t forget : :)

$config['csrf_protection'] = FALSE;

enjoyed this post? share with others:

twitter stumble upon digg

This entry was posted on Thursday, July 26th, 2012 at 12:00 am and is filed under Codeigniter, PHP. You can follow any responses to this entry through the RSS 2.0 feed.
  • http://noskov.biz/ Сергей Носков

    Great article! A lot of useful things, I have something to think about. Thanks!

    P.S. “Next day, your customer called you angry and telling you about a weird error in his screen.” – it’s just about me ;)

  • Frank

    Thanks for this post!

  • netmaxos

    Great post John!

  • Mikelamar

    Good point and thanks for the heads up. We can’t just rely on libraries when it comes to security.

  • xxaxxo

    Also 1 other thing that can be added to the last advices, Always try to use tokens for your forms to check if the submit is coming from your site or not.

  • web_and_development

    Yes that’s a good idea

  • CSRF_Fan

    Why would you need to disable CSRF just because it doesn’t work in AJAX? To get it to work in AJAX, simply add the CSRF token along with the AJAX post request with

    $this->security->get_csrf_hash();

  • web_and_development

    I think you don’t understand the meaning of CSRF protection. As wikipedia says “CSRF (sometimes pronounced sea-surf[1]) or XSRF, is a type of malicious exploit of a website whereby unauthorized commands are transmitted from a user that the website trusts.”  ( http://en.wikipedia.org/wiki/Cross-site_request_forgery ) . This simply means that if you have the CSRF token in your form (as a hidden input or at your JavaScript), the bot WILL send this form from your website as a normal user. Bots can easily use JavaSript for sending forms too.

    So just to make clear, to prevent CSRF attack you have to:
    1. Add the hidden input to authorize it from your form (so yes you can add it with the $this->security->get_csrf_hash(); )
    2. You have to add it to your session as a hidden field that the user cannot see so you can prevent hack attacks.

    If you go deeply to the code of Codeigniter at system/core/Security.php at around line 206, you will see that it works by setting it in a cookie and not in the session. With this $_COOKIE I spend many hours fighting why it doesn’t work in IE 9, why it doesn’t work in Opera and so on. It is unstable that’s what I am telling. Then I realized that anyone can just create the same COOKIE and that’s it. If you want to do it with the right way you have to add it to the session. That’s my opinion. I work 1 year now with Zend Framework CSRF Validator and I never had a problem, neither with IE 7. Even when I tried Laravel solution for CSRF Protection ( http://laravel.com/docs/views/forms#csrf-protection ) I didn’t have any problem with that too.

  • Jake Smith

    All you have to do to use CRSF protection with AJAX in CodeIgniter is pass along the CSRF value with your AJAX post: csrf_test_name: $(“input:hidden[name='csrf_test_name']“).val(),

  • cyber

    I am so sorry, but your post is bad.
    The CI csrf protection is very good.

    I realized the problem you mentioned.

    But I found, the xss_token is every (F5) is get new hash. That means the browser did’t store the xss cookie.

    After that, I found this in the config.php:

    ‘cookie_secure’ = Cookies will only be set if a secure HTTPS connection exists.

    This default value is TRUE.

    Try to set FALSE. So if you use http instead of https, the browsers store the cookie, and everything goes fine. :D

  • web_and_development

    Hello there, it is good to hear a different opinion. Well to be honest this is an old article and I think it is a bit unfair for those who actually are using the CRSF protection and it is working fine for them. It was more about an article to warn people that they have to be careful as it is not as simple as just setting $config['csrf_protection'] = true; .

    I think the right thing to say is to test it to all browsers (e.g, IE 7, IE 6) and if it works for them that’s fine. I also support csrf_protection now to grocery CRUD as well but I didn’t announced it as for me was unstable to legacy browsers such as IE 7 and IE 8.

    One last thing that I want to say is that at the last Codeigniter version 2.1.3 they’ve changed a lot the functionality of csrf_protection so it should be more stable and that’s a good thing.

  • http://twitter.com/HelloFarhan Farhan Farook

    Now solution ready !!!

    You can use codeigniter’s default CSRF token…

    Step – 01

    $config['csrf_protection'] = TRUE;

    Step – 02

    Replace the following code in system/core/security.php

    /**
    * Verify Cross Site Request Forgery Protection
    *
    * @return object
    */

    public function csrf_verify()
    {
    // AJAX check
    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == ‘xmlhttprequest’)
    {
    // If it’s not a POST request we will set the CSRF cookie
    if (strtoupper($_SERVER['REQUEST_METHOD']) !== ‘REQUEST’)
    {
    return $this->csrf_set_cookie();
    }

    // Do the tokens exist in both the _POST and _COOKIE arrays?

    if ( ! isset($_REQUEST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]))
    {
    $this->csrf_show_error();
    }
    // Do the tokens match?
    if ($_REQUEST[$this->_csrf_token_name] != $_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($_REQUEST[$this->_csrf_token_name]);

    }

    else

    {

    // If it’s not a POST request we will set the CSRF cookie

    if (strtoupper($_SERVER['REQUEST_METHOD']) !== ‘POST’)

    {

    return $this->csrf_set_cookie();

    }
    // Do the tokens exist in both the _POST and _COOKIE arrays?

    if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]))
    {
    $this->csrf_show_error();
    }
    // Do the tokens match?
    if ($_POST[$this->_csrf_token_name] != $_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]);

    }

    // Nothing should last forever

    unset($_COOKIE[$this->_csrf_cookie_name]);

    $this->_csrf_set_hash();

    $this->csrf_set_cookie();

    log_message(‘debug’, ‘CSRF token verified’);

    return $this;

    }

    Step – 03

    set the parameters in ajax requests…

    formData : {
    “security->get_csrf_token_name()?>”: “security->get_csrf_hash()?>”
    },

    See the magic…. Hope it will kick off csrf_protection problem of codeigniter..

  • http://twitter.com/bluetidepro Zach Reed

    Can you further explain your code? Also on Step 3, I don’t fully understand?

  • http://twitter.com/HelloFarhan Farhan Farook

    Ok zach.

    Step 1:

    Set $config['csrf_protection'] = TRUE; in your config.php

    Step 2:

    copy and replace the above function in system/core/security.php

    Step 3:

    When send the ajax requests set Codeigniter’s CSRF token and value manually. It is very important.

    Jquery Example:

    $.post(url, {‘csrf_token_name’: ‘value’}, function(){
    // do your stuff here
    });

    Therefore to set codeigniter’s default token and value you have to use following code.

    csrf_token_name = echo security->get_csrf_token_name();

    csrf_token_value = echo security->get_csrf_hash();

    it is working fine when use jquery uploaders such as uploadify, fine uploader and etc.

    Cheers !!!

  • http://twitter.com/Korrigan33 Hugo Vacher ❄

    Cross Site Request Forgery conists in sending a request to you website from another website. Another website cannot create a cookie on you website. The only point is to be shure that the user submited the form himself.

  • http://twitter.com/Korrigan33 Hugo Vacher ❄

    Wow that’s exactly what codeigniter csrf protection does…

  • Jarrod Mosen

    I cannot believe what I just read

  • http://uzaklab.com/ Wahyu Kristianto

    LOL.. You don’t know about CI

  • Jan

    Great again. Thanks!