Handling PHP Sessions With Multiple Front End's - php

We have 2x pfSense FW's in HA, behind that, 2x Zen Load Balancers in Master/Slave Cluster, behind those, 3x Front End web stack servers running NGinx, PHP-FPM, PHP-APC. In that same network segment, there are 2x MySQL DB Servers in Master/Slave replication.
PHP sessions on the front ends should be "cleaned up" after 1440 seconds:
session.gc_maxlifetime = 1440
.
Cookies are expired when the users browser closes:
session.cookie_lifetime = 0
Today, we were alerted by an end user that they logged in (PHP based login form on the website), but were authenticated as a completely different user. This is inconvenient to say the least.
The ZLB's are set to use Hash: Sticky Client. They should stick users to a single Front End (FE) for the duration of their session. The only reason I can think of this happening is that two of the FE's generated the same PHP Session ID, and then somehow the user was unlucky enough to be directed to that other FE by the LB's.
My questions are plentiful, but for now, I only have a few:
Could I perhaps set a different SESSID name per front end server? Would this stop the FE's generating session ID's that were the same? This would at least then result in the user getting logged out rather than logged in again as a different user!
We sync the site data using lsyncd and a whole bunch of inotifywatch processes, but we do not sync the /var/lib/php directories that contain the sessions. I deliberately didn't do this... I'm now thinking perhaps I should be syncing that. lsyncd will be able to duplicate session files across all 3 front ends within about 10seconds of the sessions being modified. Good idea as a temporary fix?
Lastly, I know full well that the client should be using the DB to store sessions. This would completely eradicate it being able to duplicate the session ID's. But right now, they are unwilling to prioritise that in the development time-line.
Ideas very much welcome as I'm struggling to see an easy way out, even as a temporary measure. I cant let another client get logged in as a different user. It's a massive no-no.
Thanks!!

Judging by your question you are somewhat confused by the problem - and its not clear exactly what problem you are trying to fix.
Today, we were alerted by an end user that they logged in (PHP based login form on the website), but were authenticated as a completely different user
There's potentially several things happening here.
Cookies are expired when the users browser closes:
Not so. Depending on how the browser is configured, most will retain session cookies across restarts. Since this is controlled at the client, its not something you can do much about.
PHP sessions on the front ends should be "cleaned up" after 1440 seconds
The magic word here is "after" - garbage collection is triggered on a random basis. Session files can persist for much longer and the default handler will happily retrieve and unserialize session data after the TTL has expired.
Do you control the application code? (if not, your post is off-topic here). If so, then its possible you have session fixation and hijack vulnerabilities in your code (but that's based on the description provided by the user - which is typically imprecise and misleading).
Its also possible that content is being cached somewhere in the stack inappropriately.
You didn't say if the site is running on HTTP, HTTPS or mixed, and if HTTPS is involved, where the SSL is terminated. These are key to understanding where the issue may have arisen.
Your next steps are to ensure that:
you have logout functionality in your code which destroys the session data and changes the session id
that you change the session id on authentication
That your session based scripts are returning appropriate caching information (including a Varies: Cookie header)
It is highly improbable that 2 systems would generate the same session id around the same time.
Really you want to get away from using sticky sessions. It's not hard.
You've got 2 layers at your front end that are adding no functional or performance value, and since you are using sticky sessions, effectively no capacity or resillience value!!! Whoever sold you this is laughing all the way to the bank.

Related

Session regenerate causes expired session with fast AJAX calls

My application is a full AJAX web page using Codeigniter Framework and memcached session handler.
Sometimes, it sends a lot of asynchronous calls and if session has to regenerate its ID (to avoid session fixation security issue), the session cookie is not renewed fast enough and some AJAX calls fail due to session id expired.
Here is a schematic picture I made to show clearly the problem :
I walked across the similar threads (for example this one) but the answers doesn't really solve my problem, I can't disable the security as there is only AJAX calls in my application.
Nevertheless, I have an Idea and I would like an opinion before hacking into the Codeigniter session handler classes :
The idea is to manage 2 simultaneous session Ids for a while, for example 30 seconds. This would be a maximum request execution time. Therefore, after session regeneration, the server would still accept the previous session ID, and switch to session to the new one.
Using the same picture that would give something like this :
First of all, your proposed solution is quite reasonable. In fact, the people at OSWAP advise just that:
The web application can implement an additional renewal timeout after which the session ID is automatically renewed. (...) The previous session ID value would still be valid for some time,
accommodating a safety interval, before the client is aware of the new
ID and starts using it. At that time, when the client switches to the
new ID inside the current session, the application invalidates the
previous ID.
Unfortunately this cannot be implemented with PHP's standard session management (or I don't know how to do that). Nevertheless, implementing this behaviour in a custom session driver 1 should not pose any serious problem.
I am now going to make a bold statement: the whole idea of regenerating the session ID periodically, is broken. Now don't get me wrong, regenerating the session ID on login (or more accurately, as OSWAP put it, on "privilege level change") is indeed a very good defense against session fixation.
But regenerating session IDs regularly poses more problems than it solves: during the interval when the two sessions co-exist, they must be synchronised or else one runs the risk loosing information from the expiring session.
There are better (and easier) defenses against simple session theft: use SSL (HTTPS). Periodic session renewal should be regarded as the poor man's workaround to this attack vector.
1 link to the standard PHP way
your problem seems to be less with the actual speed of the requests (though it is a contributing factor) but more with concurrency.
If i understand right, your javascript application makes many (async) ajax calls - fast (presumably in bursts)- and sometimes some of them fail due to session invalidation due to what you think is speed of requests issue.
Well i think that the problem is that you actually have several concurrent requests to the server, while the first one has its session renewed the other essentially cannot see it because the request is already made and waits to be processed by the server.
This problem will of course manifest itself only when doing several requests for the same user simultaneously.
Now The real question here - what in your application business logic demands for this?
It looks to me that you are trying to find a technical solution to a 'business' problem. What i mean is that either you've mis-interpreted your requirements, or the requirements are just not that well thought/specified.
I would advice you to try some of the following:
ask yourself if these multiple simultaneous requests can be combined to one
look deeply into the requirements and try to find the real reason why you do what you do, maybe there is no real business reason for this
every time before you fire the series of requests fire a 'refresh' ajax request to get the new session, and only on success proceed with all the other requests
Hope some of what i've wrote help to guide you to solution.
Good luck

Cakephp/php user sessions swapping for a subset of our customers

There's a bug, which we can not replicate, which involves users in one specific region of our enterprise customers swapping. For example, a user logs in as themselves on the login page, and when arriving at the home, they are another user.
It seems like accidental session hijacking, here are the clues:
cakephp security is set to low (this only means the cookie doesn't
rewrite every page load, and the the cookie does not do a user agent
check )
our cookie is set to not care about subdomains (.example.com instead of example.com)
enterprises users areredirected using a 302 if they login to the wrong area (should we use 303?)
there was a 301 accidentally sent out, but users are able to replicate
all the affected users are behind a single router, sharing internet via Sprint MPLS
all the affected users may be using computers issued by the customer
their IT claim there is no proxy cache, and no remote VPN access, yet they claim to be able to replicate the issue from home computers and off the network.
Since we can not replicate the issue in any way, we can only assume that the issue is specific to their network.
How can we prove that their network/computers are causing the session swapping? Or, what configuration on our end could be causing this, when no other users experience this issue?
[edits/updates]
Responding to some direction provided by comment - our traffic is not large enough to send duplicate IDs. (the statistically probability is too low to see what we've seen the customer replicate ).
see also:
Zend Framework Session swapping issue
why is php generating the same session ids everytime in test environment (WAMP)?
Update:
We use FCGI, and apparrently mod_php is required to understand x_forwarded_for
What's wrong with this function call?
This may be a problem with improper session invalidation in the log out. please ensure that all the variables in the session are properly terminated or explicitly null terminate every object in the session and then invalidate the session.
The second reason may be the use of variables check for static variables in your code. improper use of static variables may also cause this intermittent issue.
Use logger to log session id mapped to the user ids that can narrow down your problem and help you understand what exactly happening.
Invalidating the existing session in login action and creating a new session and copying content to the new session will help a lot.
First, do not assume the customer is at fault. It may an issue on their side or yours. Do not make an assumption as to which before testing.
Regardless of who's fault it is, the burden is on you to fix or help fix it.
First, having one user become another is often the result of a Session ID problem. The security level you have set in Cake does not regenerate the Session ID for every request.
I would start by logging the $session->id() as a user both inside and outside your local network. Then compare to see if the session id is ever the same or ever an empty string. One fix for this is to generate a unique id for each user.
If the Session ID is unique for each instance, you may want to test it under load.
The point is to test first and make conclusions based upon findings, not speculation.

Am doing online Quiz type of script in PHP. It is better to use cookies or sessions

Am doing online Quiz type of script in PHP. User needs to attend 50 Question in 45 minutes.
After that time it should close the page or Submit the answer to the next page.
It is better to use cookies or sessions. How can i do that.
Am novice in session concept so can u suggest the suitable code.
Awaiting the earliest reply
I assume, as this is a quizz, you'll count point, record ranks, etc. So your users will eventually try to cheat.
Therefor, I would recommend sessions which are only server-side.$_SESSION is an array, like $_GET and $_POST, unique to every user using your website. You can put and retrieve anything when you want.
The only thing client side is a special cookie, called PHPSESSID, which is your visitor's id, used by PHP to retrieve his $_SESSIONarray.
Only things you have to do is to begin every page with session_start(); , before any instructions (except if you use buffering like ob_start())
The main difference between cookies and sessions is where the data is stored.
With cookies, you send the data to the browser, and the browser keeps sending it back to you with every request thereafter.
With sessions, you're storing the data in memory, and then just setting one cookie that has an ID to identify the chunk of space in the server's memory where the data is stored.
The crucial difference is that when the data is stored in cookies:
it can be edited by the user
it can be seen on the network as requests are made
it adds to the weight of each request in additional bandwidth required
it takes up less server memory
When data is stored in the session:
it can't be accessed by the user without going through you
it's not sent back and forth with each request (only the session ID cookie is)
but it takes up memory on the server
it can cause issues on larger sites when needing to move to multiple web servers
I would say it depends on scale. For a lot of questions, those cookies will get heavy and make each request very large. If you quiz is running in an environment that is spread across multiple front-end web servers, sessions might be out of the question.
I suspect the deciding factor is going to be the integrity of the quiz though. If it's crucial that the user can't change the data (such as previous answers, a running score or a timestamp for the start of the quiz) then you'll need to store the data out of their reach, which means using sessions.

Safe timeout value for codeigniter session class?

I am using codeigniter's session class to handle my PHP sessions. One of the session variables automatically created on every visit to the site is session_id:
The user's unique Session ID (this is a statistically random string with very strong entropy, hashed with MD5 for portability, and regenerated (by default) every five minutes)
On my site I need to have functionality to track unregistered user's and I currently have this implemented by comparing the visitor's session_id with a stored id value in a VISITOR table in the database. This works perfectly except for the fact that the session id times out every five minutes. I would like my application to remember visitors for longer than 5 minutes (kind of like what SO does when you post a question or answer without registering).
My question is this: can you see any security issues with simply extending the regeneration time of the session class (to something like 12 hours)?
Update: based on the answers I've seen so far, it seems like its more of a performance concern rather than a safety issue. Its kinda weird how the codeigniter session class works because when creating a new session, it also creates a new cookie which seems to persist as long as the session. I guess I could create another cookie with the session ID that lasts as long as I need it to. But how much of a performance concern would it be if I were to save the sessions for something like 12 hours? Would it slow things down unless I have millions of unique visitors within a 12 hour period (in which case I'd have bigger problems to worry about...)?
Two things with that idea :
If users go away from their computer (without locking it / closing their browser), someone else might use it to go to your site with their account
well, that's probably not your problem
if you have some login/password fields, your users probably already have their login+password memorized by the browser anyway (well, for the registedred ones, anyway -- and those probably have more "power" than not registered ones)
If you have lots of users on your site, you will have more session files
as sessions are stored in files
(same if they are stored in DB / memcached -- in which case you must ensure you have configured memcached so there is enough RAM to store more sessions)
So, yes, there is a small security risk ; but I don't think it is really relevant.
Another idea would be to keep a short session lifetime, but to store some informations in cookies, with a lifetime more important than that ?
Enough information, actually, to allow re-creation of a new session, without the user noticing anything ?
But, yes, that would require a bit more work on your side...
To add a bit more precisions after your edit :
Its kinda weird how the codeigniter
session class works because when
creating a new session, it also
creates a new cookie which seems to
persist as long as the session.
This is the "standard" way of dealing with sessions -- at least, in PHP :
The session's data is stored in a file, on disk, on the server
and a cookie is used to keep a "link" between a user, and the file containing his session's information. Without that cookie, there would be no way of knowing which one of those files contains the session of a specific user.
But how much of a performance concern
would it be if I were to save the
sessions for something like 12 hours?
If you're having millions of users on your site, this will means having millions of files, each one containing the session's data of one user -- and it's not good to have too many files.
But is you are having a few hundreds user, that should be allright, I guess.
Depending on the amount of visitors to your site, saving sessions for 12 hours may not be a good idea. Why not use cookies? This is dependent on whether or not the user has it enabled in his browser though: http://www.php.net/setcookie.
One Security Tip:
Leave True on sess_match_useragent(application/config/config.php)

Caching variables in the $_SESSION variable?

I'm making a php web application which stores user specific information that is not shared with other users.
Would it be a good idea to store some of this information in the $_SESSION variable for caching? For example: cache a list of categories the user has created for their account.
This would be an appropriate use of the session mechanism as long as you keep this in mind:
Session does not persist for an indefinite amount of time.
When pulling from session, ensure you actually got a result (ASP.NET will return NULL if the Session has expired/cleared)
Server restarts may wipe the session cache.
Do this for convenience, not performance. For high-performance caching, choose an appropriate mechanism (i.e. memcached)
A good usage pattern would be like this (ether cookies or session):
User logs in
Store preferences (background color, last 10 records looked at, categories) in session/cookie.
On rendering of a page, refer to the Session/Cookie values (ensuring they are valid values and not null).
Things not to do in a cookie
Don't store anything sensitive (use session).
A cookie value should not grant/deny you access to anything (use session).
Trap errors, assume flags and strings may not be what you expect, may be missing, may be changed in transit.
I'm sure there is other things to consider too, but this is just off the top of my head here.
That could work well for relatively small amounts of data but you'll have to take some things into consideration:
$_SESSION is stored somewhere between requests, file on disk or database or something else depending on what you choose to use (default to file)
$_SESSION is local to a single user on a single machine.
sessions have a TTL (time to live), they dissapear after a set amount of time (which you control)
Under certain circumstances, sessions can block (rarely an issue, but i've run into it streaming flash)
If the data you mean to cache is to be accessed by multiple users you're quickly better off caching it seperately.
If you only want this data available during their session, then yes. If you want it available tomorrow, or 4 hours from now, you need to save it to a database.
Technically you can modify the sessions to have a very long lifespan, but realize if they use a different computer, a different browser or flush their cookies they will loose the link to their session, therefore anything serious you should create a type of user account in your application, link the session to their account and save the data in a permeate place.

Categories