Wednesday, March 13, 2013

CodeIgniter sessions: timeouts, AJAX, and Remember Me

I love CodeIgniter. It's among the top 3 popular PHP frameworks, though the order of those 3 is a matter of opinion and taste.

Back in February I finally got to research and work around an issue that had been driving me nuts. I have an app which requires login, and uses CI sessions. Using one particular page, after a while my AJAX calls will fail because I am no longer logged in. Reload the page, yep, I'm logged out.

Turns out, this is a known issue, going way back:
CodeIgniter regenerates a new session ID periodically, to prevent session ID hijacking (session fixation attacks). At some point my session ID will change, and my session will effectively expire because the AJAX requests aren't setting the new session ID in my browser.

https://github.com/EllisLab/CodeIgniter/issues/154

This goes beyond AJAX, though. If you want the session to stay open over time, e.g. a Keep Me Logged In functionality, you will also see this problem: when you open the site tomorrow, your session ID is out of date and you're not Keeping Logged In at all.


Fortunately, the fix for this is not difficult.

Session Expiration & Session ID Regeneration


Open up config.php and look for these two session variables.
The sess_expiration setting, defines how long a session is good (idle time since last hit).
The sess_time_to_update setting, defines how often your session ID will be regenerated.
$config['sess_expiration'] = 86400 * 30; // 30 days
$config['sess_time_to_update'] = 300; // 5 minutes
Our problem is the session ID regeneration. We can effectively disable this by making sess_time_to_update very, very long:

// sessions are good for 30 days, and IDs will change every year
$config['sess_time_to_update']    = 86400 * 365;




Problem solved. I only need to login after 30 days of idle time, and even using AJAX-heavy pages without

Consequence: Session Fixation

Disabling session ID regeneration does have a consequence for security, though. Now that your session ID doesn't change, it's hypothetically possible for someone to snag your session ID and use it indefinitely (well, for a year if you set it as above).

This can be mitigated by a few other arrangements:

Shorten the session expiration and regeneration time. Do they really need a session to be good for 30 days? Would 7 days suffice? How about 3 days? The shorter it is, the less time you give a sniffer to try hijacking your session before finding it already expired.

Encrypt the cookies! Set sess_encrypt_cookie to TRUE and set a random encryption_key so thesession IDs can't be intercepted in the first place. Do a Google search for "codeigniter encryption key generator" and take your pick.


Enable user agent matching. The sess_match_useragent setting enables a check on your session, that you're using the same browser as you were when the session opened. User agent strings can be faked, but this does increase the "cost" of brute forcing or hijacking sessions, as the hacker must try the session key several times as they guess browsers.

Enable IP address matching. The sess_match_ip setting enables a check that your IP address hasn't changed since your session was last used. This one may not be appropriate if your ISP routes traffic through changing proxy servers (satellite Internet, America Online) and most of us have dynbamic IP addresses that change every few days. But, if your use case is access from a fixed IP address such as an office intranet, or you can tolerate logging back in after your reset your home router, this can provide a significant layer of security.

Use SSL. This isn't always possible, but when it is, intercepting sessions is impossible. If you use this and also cookie encryption, then intercepting sessions is doubly impossible.

Conclusion

This solution to session timeouts works fine, but opens up a security consideration. Fortunately, with cookie encryption, this security consideration doesn't need to be a security problem and your users can Keep Me Logged In without having their sessions hijacked.

6 comments:

  1. Thank you. This problem drives me insane! I will abandon CodeIgniter over this issue! I have seen similar articles, but this one extends the time a lot longer, and gives additional info about security. Thanks! Let's see how this goes!

    ReplyDelete
  2. I wouldn't go so far as to abandon CodeIgniter. The issue would happen with any system which prevents session fixation, by changing the session keys periodically. In CI, simply change the sess_time_to_update as I pointed out. If a session is only good for 24 hours, but will regenerate after one week... then session fixation isn't likely to happen, but nor is your AJAX behavior likely to be interrupted by regeneration.

    ReplyDelete
  3. Thank you. m fade up with this problem bt now solved.. read lots of articles bt finally urs gave me sol.

    ReplyDelete
  4. thank it very clearly explain the session in codeignator rather then all other

    ReplyDelete
  5. It's really helpful because of nice explanation about session expiry and session time to update.

    ReplyDelete
  6. This comment has been removed by a blog administrator.

    ReplyDelete