Welcome Guest, Not a member yet? Register   Sign In
Session data security: what happens when session cookie & ci_sessions table don't match?
#1

[eluser]aidehua[/eluser]
Despite multiple re-readings of the session class page in the User Guide, I'm struggling to get a handle on the way CodeIgniter handles sessions. I'd be really grateful for any insight.

When the sess_use_database config item is set to TRUE, where is the session data being stored? Is it just in the ci_sessions database table? Or in the session cookie as well?

Is all the session data being passed (in clear text, unless sess_encrypt_cookie is used) from client to server in the cookie at each request, or just the session_id?

I'm thinking from a security standpoint.

To take a trivial/oversimplified example, if I have a session variable called "has_absolute_power", does the user simply have to spoof their session cookie to include "has_absolute_power = TRUE" to be able to wreak havoc?

In other words, what happens when, perhaps because of a hack attempt, the session data in the session cookie doesn't match the data stored in the ci_sessions table? Is the database slavishly updated to match the cookie, or the cookie updated to match the database? Or does CI recognise that something fishy is going on and destroy the session automatically?

Thanks.
#2

[eluser]davidbehler[/eluser]
All data will be stored in the ci_sessions table.
The only thing that stored in a cookie is the session_id that corresponds to a row in the ci_sessions table.

The user might try to edit his cookie and change the session_id, but that will be no use as user agent and ip are checked aswell to match a users session_id to a row in the table (atleast if you activate these features in the config file). If no matching row is found, a new row is added (=session created) and a new cookie with another session_id is set.
#3

[eluser]aidehua[/eluser]
Thanks waldmeister.

So if I set a session variable "is_logged_in = TRUE" (perhaps a bit more realistic than "has_absolute_power = TRUE"), that value is stored in the database only, and I can be pretty confident that I can trust it?

I just tried an experiment. I wanted to see what was in my session, so I wrote this:

Code:
foreach ($this->session->userdata as $key=>$item):
                echo $key . ': ' . $item;
                echo '<br />';
        endforeach;

This returned the following:

Quote:session_id: 7df9aa7a983e43b1c0215b2e844a039a
ip_address: 127.0.0.1
user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Ap
last_activity: 1262938987
username: xxxxxx
logged_in: 1

Then I went directly to the database (using phpMyAdmin, so outside of CodeIgniter's scope) and changed the custom data manually so that the username was now "yyyyyy" rather than "xxxxxx".

Then when I ran this code again:

Code:
foreach ($this->session->userdata as $key=>$item):
                echo $key . ': ' . $item;
                echo '<br />';
        endforeach;

The print-out was as follows:

Quote:session_id: 7df9aa7a983e43b1c0215b2e844a039a
ip_address: 127.0.0.1
user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Ap
last_activity: 1262938987

i.e. ALL the custom session data was somehow removed from the session userdata array. (Same session_id, same ip_address & user_agent.)

BUT that data was still there in the database, including the amended custom data (username = 'yyyyyy').

When I went back to the database and changed the username back to 'xxxxxx', and ran the code again, the custom data was restored to the print-out:

Quote:session_id: a8e11d3422c5ca0b4b640d0982c09c2c
ip_address: 127.0.0.1
user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Ap
last_activity: 1262944815
username: [email protected]
logged_in: 1

What's going on there?
#4

[eluser]davidbehler[/eluser]
Ok, sorry for that.
I forgot that the session library I'm using is slightly different from the one that comes with CI.

Anyway, the user guide says
Quote:When session data is available in a database, every time a valid session is found in the user's cookie, a database query is performed to match it. If the session ID does not match, the session is destroyed. Session IDs can never be updated, they can only be generated when a new session is created.
and in my opinion it's about the same behaviour that I described. Only that the data is indeed saved in both the database and the cookie, but as soon as either side is tempered with and the data does not match anymore a new session will be created.
#5

[eluser]aidehua[/eluser]
Thanks for the update & your help.

A couple of things:

1. If ALL the data is stored in the cookie AND the database (I think the user guide is a bit ambiguous about that), then it would not be a good idea to store sensitive data in the session. If the cookie stored only the session ID, and the rest of the session data was only in the database, this would be less of a problem.

Also, if all the data is stored in the cookie AND in the database, then the 4kb cookie size limit remains. I thought that using the database to save session data was designed to get round this limitation.

2. The user guide does say, as you point out, "If the session ID does not match, the session is destroyed." But in the example I gave above, the session ID was unchanged; it was the custom session data that I changed and so presumably was no longer matching between database and cookie. And the session didn't seem to be destroyed - it just lost its custom data. And the custom data was restored as soon as I set it back to its original value.

I'm still a bit confused by this behaviour...
#6

[eluser]JanDoToDo[/eluser]
I would also like to know if anyone has any thoughts on this?? Smile
#7

[eluser]WebsiteDuck[/eluser]
My only guess is that you somehow corrupted user_data so that it couldn't be unserialized by codeigniter, so codeigniter threw away all the custom data...
#8

[eluser]aidehua[/eluser]
WebsiteDuck:

I think you're right. The problem was that I didn't understand how "serialising" data worked. But your post has caused me to work it out. Or to guess-work it out, anyway. So thanks.

Before I changed the user_data in the database, it was:

Quote:a:8:{s:4:"role";s:1:"9";s:8:"username";s:8:"[email protected]";s:7:"user_id";s:1:"1";s:12:"is_logged_in";s:1:"1";}

After I changed it:

Quote:a:8:{s:4:"role";s:1:"9";s:8:"username";s:8:"[email protected]";s:7:"user_id";s:1:"1";s:12:"is_logged_in";s:1:"1";}

i.e. I just added "XX" to the username. I didn't think that would corrupt the data.

But now I realise that the "s:x" prefixing each sub-string refers to the length of the subsequent string. e.g. "s:8" indicates an 8-character string. So if I add "XX" to the username string, I should have changed "s:8" to "s:10".

I've checked this experimentally and it now works as expected.

Also, experimentally, when I change the user_data in the database, the new user_data values are returned when I request the session data in CodeIgniter. This indicates to me that when the database and session cookie values don't match, the database values take precedence. Which I think is how it should be, because it prevents the user from manipulating their session data by manipulating their cookie.
#9

[eluser]C4iO [PyroDEV][/eluser]
Just wanted to say this topic was VERY clarifying about CI Sessions behavior.




Theme © iAndrew 2016 - Forum software by © MyBB