ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

My big fear about storing session data directly on cookies

June 20, 2008 3:27pm

Subscribe [7]
  • #1 / Jun 20, 2008 3:27pm

    fredpyo

    4 posts

    Hello everyone, I think this is my first post here on the forums, so… hi!

    I’ve been messing around with CI for about 6 months now… And for the last 2 months, I’ve been working on a porject for a client.

    During the development, we discovered that certain pages did not display correctly on some computers, specifically some that were using a Squid proxy. It took me some time to determine what the problem was. But I think I nailed when when I used Firefox’s majestic Firebug.

    The setcookie header is… HUGE!

    The problem was that the page that couldn’t load was one that had plently of flashdata session variables. And thanks to Firebug I discovered that the session data was stored… like this:

    Server response
    —HEADER—
    setcookie: ci_session=ci_session=a:14:{s:10:“session_id”;s:32:“fb48635c97fcd2ad37a01f31470cad5e”;s:10:“ip_address”;s:12:“200.3.249.98”;s:10:“user_agent”;s:50:“Mozilla/5.0+(X11;+U;+Linux+i686;+es-ES;+rv:1.8.0.9”;s:13:“last_activity”;i:1213985065;s:24:”
    ... and that appears repeated N times (N being the amount of flash variables that I want to store on the session… including old and new flashdata).
    —BODY—
    <html>
    ...
    </html>

    Pasting that into a wordeditor returned a wooping 22KB just for the session variables!!!

    I looked deeper into the session handling class and - I might be totally mistaken about this - it seems to call the setcookie php funcion for every variable I want to save, concatenating each time the variables that were stored before with the new variable!


    So, like I said, I might be totally wrong about this… but… is this a problem/bug?

    I really need to get this session stuff fixed… so I’m about to pull my sleeves and sit down and hack the session and view codes. Something like setting the cookies just once just before the first view is loaded or something like that (I really should that a look at how the views are actually loaded before I make any other bold statements, shouldn’t I?).


    But, besides that tiny detail, CI is fantastic!
    Thanks in advance for the aid.

    Federico Cáceres

  • #2 / Jun 20, 2008 4:31pm

    attos

    58 posts

    I use database sessions. The cookie only stores the session ID.
    Look into the documentation. The wiki also has some information about it.

  • #3 / Jun 20, 2008 5:32pm

    fredpyo

    4 posts

    Yes attos, I’ve thought about database sessions, I was even going to try them this weekend, I need that extra layer of security.

    But… still it doesn’t change the fact of what’s going on up there with the cookies!

  • #4 / Jun 20, 2008 11:51pm

    attos

    58 posts

    What is the security layer you need?
    Due to the inherent connectionless of the HTTP protocol, you need to maintain some session data or identifier between the server and the client. This can be achieved with cookies, hidden fields on URL encoded.
    I see no security issues sending and retrieving a session id with cookies, as long as there is no direct connection from the client to the database.

  • #5 / Jun 21, 2008 10:14am

    Popcorn

    225 posts

    Database sessions are your best bet.

    You can view the different 3rd party ones here :

    http://codeigniter.com/wiki/Category:Session/

  • #6 / Jun 21, 2008 10:31am

    Crimp

    320 posts

    This topic pops up from time to time.

    Like most, I fully understand that leaving important information client site opens it up for tinkering and tampering.

    That’s the theory.

    What I don’t know is how easy or hard it is to hack into an encrypted cookie and bake your own.

    Would the Ellislabers really leave the back door to CI wide open?

    I doubt it.

  • #7 / Jun 21, 2008 10:36am

    Popcorn

    225 posts

    It shouldn’t be too too hard to create your own “fake” session because anyone can download CodeIgniter and view how the session is crafted.

  • #8 / Jun 21, 2008 12:07pm

    Crimp

    320 posts

    Yeah, I keep hearing that EVERY time. It shouldn’t be too hard. Right?

    OK.

    $cookie_data = $this->CI->encrypt->encode($cookie_data);

    OK.

    /**
         * Encode
         *
         * Encodes the message string using bitwise XOR encoding.
         * The key is combined with a random hash, and then it
         * too gets converted using XOR. The whole thing is then run
         * through mcrypt (if supported) using the randomized key.
         * The end result is a double-encrypted message string
         * that is randomized with each call to this function,
         * even if the supplied message and key are the same.
         *
         * @access    public
         * @param    string    the string to encode
         * @param    string    the key
         * @return    string
         */
        function encode($string, $key = '')
        {
            $key = $this->get_key($key);
            $enc = $this->_xor_encode($string, $key);
            
            if ($this->_mcrypt_exists === TRUE)
            {
                $enc = $this->mcrypt_encode($enc, $key);
            }
            return base64_encode($enc);        
        }

    I just hit the stop watch.

    Good luck.

  • #9 / Jun 21, 2008 3:51pm

    Popcorn

    225 posts

    Actually, I retract my previous statement. I totally forgot about the encryption key you have to set within the configuration file. Unless the users hack into your website they would have a very minimal chance of creating a fake session cookie.

  • #10 / Jul 07, 2008 3:08am

    Chillahan

    57 posts

    So Federico is saying the default session handling assigns one cookie for each session item - ouch!  One would think out would serialize the data.  But, when I inspect my cookie, I only see one cookie.  Perhaps it uses additional cookies for Flash data only?

    I hope it’s managing garbage collection and not adding on to the cookie(s) length each time we update an existing session item’s value.  Can someone confirm?

    Personally, I don’t mind using cookie-based sessions.  I use the CI database feature to at least AUTHENTICATE the session, though (and I do encrypt it).  I just wish CI would add similar functionality for “remember me” logins, so that I don’t have to use an insecure cookie separately for that using the cookie helper functions.  I’ve been thinking of setting two cookies though, one with a salt value that is randomly assigned to each user’s account upon logging in and selecting “remember me” - this way at least someone can’t just create a counterfeit cookie and mimic ANY user.  Again, this is what the CI native session class does with its cookie(s) when you enable the database option.

  • #11 / Jul 30, 2008 8:36pm

    fredpyo

    4 posts

    Ouch, I’ve been a long time out :S.
    Thanks for the interesting replies!

    Today I faced the aforementioned CI app. And today was a good day, after half an hour or so I got it fixed.

    ....

    It all began with me tinkering a little bit more with setcookie function.

    Turns out, that in my current installation, code like this:

    setcookie('test',1);
    setcookie('test',2);
    setcookie('test',3);

    Prints the following headers:

    Set-cookie: test=1 test=2 test=3

    Instead of:

    Set-cookie: test=3

    So… I read a little bit more, and tested a little bit more. It turns out that in my server when I call setcookie, even if the variable name is the same as an existing cookie name, the previous cookie var one is not replaced by the new one, instead the new one is appended to the cookie, including the old cookie var. Odd behaviour!

    So on I went with my investigation, until using header(‘Set-cookie….’); saved the day for me.

    Doing the following “patches” to the function sess_write() in CI’s Session.php file:

    //setcookie(...) // comment setcookie for it doesn't seem to work correctly
    $cookie_data = urlencode($cookie_data);
    $expires = date("D, j-M-Y G:i:s e", $this->sess_length + time());
    header("Set-Cookie: {$this->sess_cookie}=$cookie_data; expires=$expires; path=/; ");

    (I should really place this as an extension…)

    Fun, isn’t it?

  • #12 / Jul 30, 2008 8:57pm

    Chillahan

    57 posts

    Ah, so the issue only exists if you update the same session item multiple times before outputting to the browser?  That is what your tests appear to bring to light.  If so, that’s not such a big issue, unless you have existing code that relies on being able to override existing to-be-written cookie/session data before output is flushed to the browser.

    I thought the original post was saying that all session cookie data kept appending to itself, which would seem to make lots of installations hit the 4 KB limit quickly, but I can see more exactly what his issue was now.  (which I don’t think IS an issue for most installations)

  • #13 / Jul 30, 2008 9:15pm

    fredpyo

    4 posts

    Actually, all session cookie data kept appending to itself. Each time that I accesed any session data through the CI session object, sess_write is called (normal) and thus setcookie is called (normal) but instead of replacing the old session data, the new one is appended.

    I think it might be some obscure issue with the PHP version I’m using or a configuration issue.

  • #14 / Jul 30, 2008 11:46pm

    Colin Williams

    2601 posts

    Sounds like you’re not even using the core Session class at all. Because if you were, you’d be setting cookie data with $this->session->set_userdata($array);

  • #15 / Jul 31, 2008 12:37am

    fredpyo

    4 posts

    Oh, but I am actually using the core Session class Colin 😊.

    ... Each time that I accesed any session data through the CI session object ...

    I just dug into the code to see how it worked. Under the hood, this is CI’s Session class does:
    1. From a controller, I call the following: $this->session->set_userdata($array);
    2. Inside set_userdata(), once the data is copied to the data array, $this->sess_write() is called
    3. sess_write() serializes the data and calls the setcookie() PHP function, which basically loads the cookie data into the headers.


    So, the following CI code:
    $this->session->set_userdata($data1);
    $this->session->set_userdata($data2);
    $this->session->set_userdata($data3);

    Results in 3 calls to PHP’s setcookie().

    That’s why in my tests, I simply called setcookie, to check if the error was a CI error or a PHP error (either because of a bug or misconfiguration) revolving around setcookie.

    Indeed I discovered that several calls to setcookie seem to append rather than replace the cookie values, patching Session.php (CI’s core session class) with header(‘Set-cookie:...’); worked just fine.


    Hope it came out clear :D.
    Did I miss anything? Did I just “patch” something that didn’t need a patch?

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases