According to the standard 2.4 documentation, the security.yml config file allows for the following configuration option:
session_fixation_strategy: none | migrate | invalidate
source: http://symfony.com/doc/current/reference/configuration/security.html
However, I fail to find any details in the official documentation (or elsewhere) on what this option actually does, or how it works in practice.
So, if I set this option to either "migrate" or "invalidate", how will this affect session handling in my system? For example, if I set it to "invalidate", would this mean that a context-local session is invalidated when the user navigates to a different security context?
In short:
NONE: the session is not changed
MIGRATE: the session id is updated, attributes are kept
INVALIDATE: the session id is updated, attributes are lost
In detail:
None strategy:
Nothing is (supposed to be) done in the default session implementation, thus the session is maintained from one context to the other.
Migrate strategy:
"Migrates the current session to a new session id while maintaining all session attributes."
(The session storage should regenerate the current session.)
"Regenerates id that represents this storage.
This method must invoke session_regenerate_id($destroy) unless this interface is used for a storage object designed for unit or functional testing where a real PHP session would interfere with testing. Note regenerate+destroy should not clear the session data in memory only delete the session data from persistent storage."
Thus the session is retained from one context to the other.
Invalidate strategy:
"Clears all session attributes and flashes and regenerates the session and deletes the old session from persistence."
Thus the session is regenerated from one context to the other.
It was not revealed by your question what kind of session data you are trying to fetch.
But in any case, no separate session is generated for different security contexts:
http://symfony.com/doc/current/reference/configuration/security.html#firewall-context
Security (authentication) related data is stored under a separate key (based on the firewall name). So for example if you have a firewall with a name 'main', the authentication token will be stored under '_security_main', if you have a firewall (a separate context) with a name 'foo', the user and related token data will be stored under '_security_foo', etc.
So besides ->getToken ->getUser (etc.) the rest of the session variables will be available in different contexts provided you use the 'none' or the 'migrate' session strategies.
Take a look at the session interface for details (quotes are from these files)
vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php
And the default implementation:
vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/Session/Session.php
Related
Regardless of a language and framework, how does this work in a low level -- putting a variable into a session to authentication a user?
put_session(curr_connection, :current_user, user.id)
Does user user saved in a cookie? On a client? Then what prevents a user of a browser change it by storing id of any user they desire and get authenticated on behalf on that user? Or does user.id get saved on a server and on a client we have only a loooooong session id, in a cookie or in url?
The short answer is it depends. All languages / frameworks have their defaults, Ruby on Rails for example stores it in a cookie by default, PHP stores it on the server, etc. But in pretty much all of these languages, you can change your cookie store to whatever you want.
Some options (there may be more):
Cookies - In this case the cookie is encrypted before sent to the client. The key used for encryption is some sort of an application setting. This is somewhat secure, because even if session values are stored on the client, a user still cannot see or modify them, because he does not have the application key. The advantage of this is that it's very simple and requires zero setup, disadvantages include this being less secure than other solutions, and also the amount of data that can be stored in a cookie is limited.
Server memory - In this case, a cryptographically random session id is sent to the client, all session data is stored in the application server memory, identified by the session id. The advantage is that it's not written to disk and also not sent to the client. Disadvantages include the session data being lost when the application server is restarted.
Server Filesystem - The traditional approach (kind of), session data is stored in files so that it's persisted across application server restarts. In this case, access control to these files is key, but usually taken care of by the language or framework.
Server SQL Database - The traditional heavy-weight approach, all session data is stored in a relational database on either the application server or a separate database server. The advantage is that you have direct control to session contents of any suer, not just the logged on one (for example it's easy to do forced logout for an admin by removing session entries from the database). This same thing can also be a disadvantage in case of an application level attack. Also operation is more expensive.
Server NoSQL Database - About the same as a relational database, but a non-relational database like Redis can also be used. One drawback can be that access control in Redis is not very strong to say the least.
Session Service - In some enterprise applications you may want to implement some kind of a session service (RESTful or else). Obviously this just pushes the problem one layer back, session data must still be stored somewhere with one of the options above.
Your language or environment probably already supports some of these, and if you want one that is not supported out of the box, you can implement your own. However, session management is tricky business, it's quite easy to make it vulnerable. OWASP has a nice session management cheat sheet to consult.
I have the following scenario:
A user logs in, a session entry via connect-redis which is valid for 2 weeks. The user can now access certain parts of the app using the session id that is stored in the app.
Now, if 1. the user deletes that cookie in the browser (with the session) and 2. logs in again - there are now 2 session entries in Redis associated with the same user, with the older one being obsolete.
What is the best way to deal with such old/obsolete sessions? Should I use a client library for redis, search through all sessions to find the ones that match the info of the currently logging in user (after she potentially manually removed the cookie), and purge these obsolete session; or is there a better way?
Gracias,
nik
That depends whether this (user deletes the cookie) is a common scenario and, if it is, whether there's a problem with obsolete cookies in the server.
Two potential "problems" that I can think of are:
Security - could the stale cookie be exploited for malicious intent? I do not see how that's possible, but I may be wrong(tm).
Storage - are the stale cookies taking too much (RAM) resources? If there's a lot of stale cookies and each cookie is large enough, this could become a problem.
Unless 1 or 2 applies to your use case, I don't see why you'd want to go through the trouble of "manually" cleansing old cookies. Assuming that you're giving a ttl value to each session (2 weeks?), outdated cookies would be purged automatically after that period so no extra action is needed to handle these.
I've been reading about sessions, both client and server side as well as few attacks possible on them. I'd like to know what are the practical solutions to the following problems related to sessions
Race condition between two request trying to change the session variables
When session ids are regenerated, what happens to the slow requests that reach the server with older session id
For your first question, see here for how ASP.NET handles this - "Synchronizing Access to the Session State":
What if other pages attempt to concurrently access the session state?
In that case, the current request might end up working on inconsistent
data, or data that isn't up to date. Just to avoid this, the session
state module implements a reader/writer locking mechanism and queues
the access to state values. A page that has session-state write access
will hold a writer lock on the session until the request terminates.
For your second question this would be down to your code regenerating the session identifier at a suitable point. For example, to avoid session fixation it is good to regenerate the session identifier upon login. At this point there should not be other, slow requests being made to the server, so therefore this is an optimal time to issue a new identifier.
In other situations it may be appropriate for your application to recognise expired session identifiers for a short time, and associate them to the new identifier until all connections have been closed.
I'm troubleshooting an issue with a server instance that I need to do some root cause analysis and right now I believe the driver is Express Sessions.
I've implemented sessions as a primary intra-page data storage mechanism, but it seems that sessions are not unique to the visitor relationship.
By this I mean that I have a session that prefills a form on a "shipping information" page. However, if I visit this page from other browsers or other machines the detail from the first session created on server start is prefilled as if the session data is bleeding into these other browser relationships.
So, I'm trying to understand if the intention for sessions is that they are unique to the visitor by default. If not, can they be made to be unique?
I'm especially worried because admin authentication is also done via sessions.
Yes they are unique to visitor, it sounds as if your code is setting some global state, and not sessions. You may want to post the config you are using, plus where you are setting session vars.
I don't know anything about cryptography. I'm wondering what the session secret is.
I see code like this:
app.use(express.session({
store: mongoStore({
url: app.set('db-uri')
}),
secret: 'topsecret'
}));
What is the secret and should I change it?
Yes, you should change it. A session secret in connect is simply used to compute the hash. Without the string, access to the session would essentially be "denied". Take a look at the connect docs, that should help a little bit.
The secret is used to hash the session with HMAC:
https://github.com/senchalabs/connect/blob/master/lib/middleware/session.js#L256
The session is then protected against session hijacking by checking the fingerprint against the hash with the secret:
https://github.com/senchalabs/connect/blob/master/lib/middleware/session.js#L281-L287
Motivation for this answer
The other answers address "Should I change it?" and provide a surface-level explanation on "What is it?" As someone who just started using express-session, I was curious and in my reading found much disagreement over whether having a secret like this is valuable and how much.
Many people discussing this topic seem to be security novices like myself. However, I came across this answer with a comprehensive explanation of the intended effect of the secret and some of the possibilities. You should read the whole answer, but I will try to summarize.
What does the secret protect against?
The type of attack in question here is session hijacking. Typically, this involves the attacker acquiring the session ID of a valid user, thereby being able to emulate that user's session and allowing the attacker to access information or act on the victim's behalf.
How can you protect against session hijacking?
A good start is to use a session ID that is suffienciently long and random, as it inhibits an attacker's ability to guess the ID. As noted by the other answer's author:
It is also critical that session ids are not generated using a predictable algorithm such as a counter because if such logic exists, the attacker is no longer guessing but generating session ids.
As an example: if an attacker finds out that your session IDs are sequential (e.g. 1, 2, 3), then if they discover a session ID of 2 then they can reasonably assume 1 and 3 are session IDs as well.
What does express-session's secret do?
The Express session middleware...calculates a hash over the combination of the session id and a secret. Since calculating the hash requires possession of the secret, an attacker will not be able to generate valid session ids without guessing the secret (or just trying to guess the hash).
So the secret is used to create a hash that is long and random. If the session ID is already sufficiently long and random, then using a secret in this manner is largely redundant. As other users have pointed out, at the end of the day, the attacker is just guessing one long and random instead of another.
But don't be so quick to dismiss the use of hashing!
express-session is a public package
An important feature of the Express session middleware is its support for user-generated session ids. This allows developer to deploy the middleware in an existing environment where session ids are generated by an existing entity which might reside on a completely different platform. Without adding a hash to the user-provided session ids, the burden of building a secure system moves from the expert (the module author) to the user (which is likely to be a security novice). Applying a hash is a much better approach than forcing an internal session id generator.
If an inexperienced user instead defines their own insecure session ID generator (e.g. say, something sequential as discussed above), hashing it will ameliorate that security flaw.
As the author notes elsewhere:
Also, this is a generic module assuming as it's core requirement a wide range of users. It absolutely has to assume that some people will use it poorly (e.g. increment ids) and accommodate that. This is also common practice when building modules for a wide audience.
Don't put all your eggs in one basket
Hashing using a secret is one layer of security, and can help cover flaws in other layers. What if your random session ID generator has a bug that can be exploited? What if you accidentally use RNG.pseudoRandomNumber() instead of RNG.strongRandomNumber() when coding? What if one of your dependencies breaks or is compromised? Once again, hashing helps patch those flaws.
There are other benefits
You can detect the difference between expired/unallocated IDs and invalid (maliciously generated) IDs:
By including an integrity component in the session id (via a hash or signature), the server can immediately tell the difference between an expired session, an unallocated session id, and an invalid session. Even if you just log invalid authentication attempts (and you should), you would want to log an expired session differently than an invalid one.
You can build a tamper-resistant timestamp into the ID:
While cookies come with an expiration policy, there is no way to ensure it is actually obeyed. (...) A common best practice is to include a timestamp in every credential issued, which can be as simple as adding a timestamp suffix to the randomly generate session id. However, in order to rely on this timestamp, we must be able to verify it was not tempered with and the way to accomplish that is with a hash or signature. (...) Adding a timestamp to the session id allows the server to quickly handle expired sessions without having to make an expensive database lookup.
You can immediately invalidate many IDs if something goes wrong:
Because generating a hash or signature requires a server-side secret or key, replacing the secret will immediately cause all session ids to fail validation. By using different secrets for different types of session ids, entire classes of sessions can be segregated and managed. Without such a mechanism, the application itself has to make a computed decision about the state of each session or perform mass database updates.
In Conclusion
The having a secret (and using it to hash) provides many benefits:
It protects users from themselves
It adds an extra layer of defense
(With a custom session ID generator) It allows detecting malicious behavior
(With a custom session ID generator) It allows bundling a timestamp into the ID
It provides a kill switch
And once again, I would like to credit this answer for everything in this post. I am just a curious onlooker!