Spring Session uses a different format for its session cookies than Tomcat does. So if you implement Spring Session, even if you would name the session cookie JSESSIONID, all the users have to login again.
This is a point where you potentially lose users, because nobody likes to login. Perhaps this is an edge case, and certainly it's not worth a huge amount of trouble, but I'm curious if it's possible for existing users to use their already stored Tomcat session cookies?
You can implement your own org.springframework.session.web.http.CookieSerializer that matches Tomcat's default cookie serialization and register it as a bean.
Spring Session configuration will then pick it up and use it - see org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration#setCookieSerializer for more details.
Related
After studying the rails guide and some other ressources I'm wondering how a session fixation attack on a user's session can actually happen. At least I'm sceptical it works as simple as depicted here in the guide, where an attacker...
1) ...creates a valid session by logging in
2) ...keeps the session alive
3) ...then forces the user to use his session's id e.g. by using some XSS vulnerability
All fine, but... how would the attacker be able to gather the value of his own session id? By default cookies are encrypted in Rails4+. So what to do as an attacker assuming I do not have access to secret_key_base or whatever is used to generate the encryption and signature keys? From what I understand I cannot tamper with the cookie without invalidating it (signature wrong) so somehow passing a self-created cookie to a possible victim is neither an option.
Is the secu guide kind of not up to date or am I missing a point here? If the latter then...
a) how [as an attacker] can I read encrypted cookie information
b) how does a vulnerability have to look like that allows me [the attacker] to inject that session id into the likewise encrypted cookie on another client? Would that be an XSS attack? The guide states that if an attacker uses code like
<script>document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";</script>
he might be able to fix that session. But again, why would rails reveal it's plain session to the client making it accessible via client-side processed javascript? It does not, which is why all my cookie-values are simple gibberish not being accessible by Javascript (can test that via console), right?
Thanks for any advice!
It's not so much about the cookie encryption (or signing). Without signing and/or encryption, the attacker wouldn't need to resort to session fixation with a site that stores session data in a cookie; they could just craft their own cookie.
Assume the attacker has a way to inject cookie-setting JavaScript onto a page that a victim will visit, i.e., an XSS vulnerability. Here's how the attack plays out:
The attacker visits the site and gets a session cookie.
The attacker crafts malicious JavaScript, exploits the XSS vulnerability, and waits for a user to visit (or lures a user to) the page containing the malicious JavaScript payload.
<script>document.cookie="_appname_session=(...attacker's session cookie...)";</script>
A victim comes along and visits the page with the malicious JavaScript, setting or overwriting their session cookie with the one from the attacker.
If they were logged in, the site will no longer recognize them as an authenticated user, and will probably redirect them to log in.
If they weren't logged in, they will be redirected to the login page.
They authenticate with their username and password.
At this point both the victim and the attacker have a cookie containing a session_id belonging to a user who has authenticated.
CookieStore, the Rails default session store
Normally you will set some value in the session to indicate that the user is authenticated. Even if it is as simple as session[:logged_in] = true, it will change the value of the cookie, and the attacker won't be able to access the site, even though the session_id is the same, because the attacker's cookie does not contain the additional data indicating an authenticated session.
Other session storage strategies
Here's where this attack is more feasible. Other session stores still use a cookie to hold the session_id, but they store session data elsewhere — in the cache, in a database, in memcached, etc. In this case, when the attacker visits the site after the victim has authenticated, the attacker's cookie — with the same session_id — will cause the session to be loaded.
HttpOnly
However, there is another major impediment to this attack — HttpOnly cookies.
Set-Cookie: _appname_session=v%2Ba...; path=/; HttpOnly
When a cookie is designated HttpOnly, as Rack/Rails session cookies are, the browser does not expose it through document.cookies. It can neither be read nor overwritten by JavaScript. I tried setting a known session cookie via document.cookie, but it was not possible unless I cleared the existing cookie(s) first. This means that an attacker would need a user who doesn't have a session cookie yet to visit the page with the XSS exploit (which would need to be on a page without a session cookie) before logging in.
As I understand it, session fixation won't work if the session details are stored in the cookie itself. The old fashioned way of doing sessions, the session data would be saved in some sort of database. The session id that got saved in the cookie would point to the record or file where the session data was saved. This means as the session changed the cookie wouldn't change at all. If a hacker had the same cookie as the user, when the user logged in they could potentially be able to hijack the login since their cookie would point to the session that now had a user_id (and potentially other data) attached to it. Under the new system, any change to the session also changes the cookie so the hackers old cookie would just have an empty session.
That being said, it's still a best practice to add reset_session to login, logout and registration endpoints (if you use something like devise this may be done for you) since if you or some future developer changes the session store to be database backed you could end up shooting yourself in the foot. The security guide also doesn't know what type of session store you are using so they have to include that advice.
We got our own central session management. Generally user can authenticate over it with an username and password, and as a result he gets an session_id. All other operations are done with that session_id. Let's say that the session management is accessed by a XML RPC.
I have two cases to implement:
Central web application made in Spring, which has login form
External web applications also made in Spring, which are relying on
passed session_id only.
Few more notices regarding system:
- session_id is stored in a cookie (after successful login, I have to add cookie to a response)
- every page request has to check session_id validity in session management system
I'm quite new to Spring, so I'm struggling to understand where and how to implement my custom logic.
My questions are:
What parts of a system I have to implement to have my own login
logic (got to have access to a response object too - to set cookie)?
I tryed something with extending UsernamePasswordAuthenticationFilter and implementing my own
AuthenticationManager, but I'm not sure that I'm going the right
way.
Is there point where/how can I implement my "every request session
check" in Spring Security manner?
session_id is stored in a cookie (after successful login, I have to add cookie to a response)
Do this in a AuthenticationSuccessHandler that is configured into your <form-login> element:
<form-login authentication-success-handler-ref="authenticationSuccessHandler"/>
External web applications also made in Spring, which are relying on passed session_id only.
Create a new filter where you check for the session_id cookie. If the cookie is not present or if it is invalid redirect to the central web application for the user to log in. If the cookie is present and valid and the user isn't already authenticated then create a new Authentication and add it to the SecurityContextHolder.
Take a look at RememberMeAuthenticationFilter.doFilter() for an example of what you want to do in your filter.
Add this filter to the filter chain using the <custom-filter> element.
I want to track a user's logon session from the time they login to my site, to the time they logoff.
Is there a pre-existing cookie I should use, or variable? I thought of using ASP.NET sessionIDs but read on StackOverflow that these numbers may change.
I would save my own Session cookie, but I don't want to do something that could be done more efficiently another way. I'm using Windows Identity Foundation (WIF) to handle my authentication layer.
The only cookie I see in fiddler is a FedAuth cookie so I assume that I might be able to derive some valuable information from it, but I don't know where / how in the WIF framework to gain access to such information.
WIF gives a bunch of events you can subscribe to. See these:
http://msdn.microsoft.com/en-us/library/microsoft.identitymodel.web.wsfederationauthenticationmodule_members.aspx
http://msdn.microsoft.com/en-us/library/microsoft.identitymodel.web.sessionauthenticationmodule_members.aspx
You can control some of the cookie characteristic via the config - A Hidden Gem: The WIF Config Schema. In particular, note the cookieHandler section and
hideFromScript - Boolean - default true Controls whether the
"HttpOnly" flag is emitted for any cookies written. Certain web
browsers honor this flag by keeping client-side script from accessing
the cookie value.
In terms of WIF, there is a Deserialize in Tokens.SessionSecurityTokenCookieSerializer and a CookieHandler (Delete / Read / Write) in IdentityModel.Web.
If I receive a request to the url host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid} and I detect a session cookie with the value: {someOtherValidNonExpiredSessionGuid}, then
Which session is the correct session to associate with the request?
Here's some background:
The pattern I am using for maintaining state across HTTP requests is to store a unique ID in the querystring, form collection and/or cookie. Then, on each request, I locate the unique Id and pull date from a database table. If the id is not valid, or the session is expired, a new session will be created (with a new id, a new cookie, etc).
The default behavior is that all forms will have a field:
<input type="hidden" name="session" value="{someGuid}" />
All links to other pages on the site will have an appended querystring parameter
a sample link
And, if the user's browsing device supports cookies, a cookie will be set having the session's value.
If I have validated that the user's browsing device supports cookies, then my form and querystring will no longer require the the session id field/parameter.
However, I am having a conceptual issue in deciding whether the session parameter of the querystring should take precedence over the cookie value or vice-versa. It seems like I could potentially get bad data in either circumstance. I could get data with a bad querystring parameter if the user bookmarked a page with the session parameter included in the URL. I could also get bad data from the cookie, if a user closes the browser without terminating the session, and the session expire-window has not yet closed. It also seems like both options could be vulnerable to a malicious user intercepting the request and sending a request with the same session information.
So, once again, my question is
If I receive a request to the url host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid} and I detect a session cookie with the value: {someOtherValidNonExpiredSessionGuid}, then Which session is the correct session to associate with the request?
I am leaning towards the cookie session, because it seems like the most common scenario will be a bookmark with the session included. I've already decided that the form post data should take the greatest precedence, because a page will always render the form with the correct ID, and the only possible situation with a wrong, non-expired ID is a very quickly implemented XSS attack, which is circumvented by including a request-scoped anti-forgery token field.
In addition to the primary question I appreciate any insight to any security-related or logical oversights I have expressed in this description. I apologize for the long post, but felt it was necessary to explain the situation. Thank you very much for your input.
Also, it is not necessarily relevant to the question, but I am using ASP.NET MVC in most situations, and setting my cookies manually with Response.Cookies.
From a security standpoint sessions should not be stored in query strings.
For example:
If sessions are stored in queries and you link to a remote host on the same page, the users valid session could be sent to the remote host via the referer header.
Sessions should always be stored in cookies.
You should try to store it in the cookie (looking the the browser caps to see if the browser supports cookies) and then have a fall back for query string.
I too would lean towards using the cookie session ID in case of ambiguity. This primarily because I'd trust the cookie implementation to be more well baked, more well tested, and more idiot-proof than my own home brewed session tracking implementation. For e.g. there are cases where ASP.NET automatically knows to clear the session cookies, renew them etc.
Also, I would design it so the cookies aren't persistent to minimize the edge cases. If the user closes the browser, then the session is closed.
The other simplification I would consider is to have either cookies or URL based tracking and not both. If the browser supports cookies, there is really no reason to also track the session through a URL.
Thoughts?
Curious ... What were your reason to rule out using the stock ASP.NET cookieless session implementation? - http://msdn.microsoft.com/en-us/library/aa479314.aspx#cookieless_topic2
If I receive a request to the url
host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid}
and I detect a session cookie with the
value:
{someOtherValidNonExpiredSessionGuid},
then Which session is the correct
session to associate with the request?
To answer your specific question, I'd recommend putting session management in the cookies as opposed to the querystring. As has been mentioned, cookies can be set to expire whereas the querystring cannot. This allows your thin-clients to assist in their own session maintenance by removing their own expired cookies. Moreover, since cookies are dropped to specific browsers, you reduce the chances of another browser spoofing the original browser session.
The only way I would use the querystring to pass session information would be as a backup method to re-establish a browser session onto a new browser instance. Here's a scenario: you have an active session using browser A on machine A which suffers some catastrophic error. You want a way to re-establish that same session on another browser instance on either the same machine or on another machine. If your code-behind can recognize that the session cookie doesn't exist, but that a valid session id exists in the querystring, you could initiate a challenge-response to verify the integrity of that session id and then drop a new session cookie on the new machine. Kinda extreme in my humble opinion, but the functionality might be useful in certain situations.
ADDED: I understand that you may want to accommodate users who have turned cookies off on their browsers, and while you can use the querystring to hold the session id I'd recommend against it. But if you must, encrypt that sucker using browser-machine specific information.
I am currently experiencing a strange issue with our users being logged out. I haven't been able to reproduce it explicitly.
The Rails application is using the default CookieStore.
My initial hypothesis is that somehow the session data within the cookie, or even the cookie itself is being destroyed. This may be either from a user clearing browser data, or something within the system that has not been caught.
As of now, the authentication system appears to be functioning as intended (Authlogic), and we are not experiencing the issue wide-spread in other components of the application.
I am considering using ActiveRecordStore to see if the problem is resolved. My understanding is the session data would be stored within the database, and if a cookie was being removed - the user would not get logged out.
Are there many known pros/cons to using CookieStore vs ActiveRecordStore?
Why is CookieStore the default when creating a Rails application, and not ActiveRecordStore?
I can answer your last two questions.
You should not use the cookie store if you're storing sensitive data in the session because you want such data to be on the server-side and not on the client.
The cookie store is the default because Rails is giving you a strong hint that you should not be storing lots of data in the session, by virtue of the fact that cookie storage is limited to 4 KB.
I think CookieStore is the default because it is simple. It doesn't require a database table.
CookieStore is not as secure as ActiveRecordStore. With CookieStore, intercepted cookies will give access to a valid session forever, even if you create a new one. With ActiveRecordStore, you can invalidate a session by removing it from the database.
See this blog post: http://www.bryanrite.com/ruby-on-rails-cookiestore-security-concerns-lifetime-pass/