A customer has requested some security enhancements to our Java web application, including the following:
According to our security team good security practices state that
session id should be changed on every request to prevent session
hijacking.
I understand the importance of allocating a new session ID upon authentication (which we already do), but this request seems a bit extreme.
If reallocating on a per-request basis, it sounds like it's no longer a session ID, but rather a single-use request ID that might be used in conjunction with a session ID.
So, my question: is such a tactic really a common security practice? If so, could somebody point me to a good discussion on the topic, implementation tips, etc.?
It doesn't hurt, but it can be really complicated and really you only need to re-generate the session id when the security level changes. See also Session Hijacking - regenerate session ID on Security StackExchange.
Generating a new session ID for each request does not make any sense and it flies in the face of the concept of a session. However, including a request ID with all requests which will cause a state change (for example, form submission) is a very sensible idea.
The intent of a per/request ID is to prevent CSRF (Cross Site Request Forgery). See: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
Related
I understand that token based authentication is widely used for microservices, esp, when there is horizontal scaling.
For microservices also, can we use sessions by storing it in database?
The series of requests would be :
First request, HTTPsession is created and session id stored in a database table along with unique
username.
Second request is sent with this session id, and any
microservice instance can serve this request. Server has to verify
this session and user with that of the database record. If sesssionid+username combo is present in database and sessionid is a valid one, then serve the request else redirect to login page.
When logout is clicked, session is invalidated and db record is also removed.
Will this not be a good session management for microservices?
Do Microservices always have to be stateless?
The reason token based authentication is used for microservices, is to avoid having to share session state between the services.
If you specifically refer to an implementation of the javax.servlet.http.HttpSession object, this is normally local to one server (service) and it would take some custom code to reload this based on the session id provided, if at all possible in your particular runtime (don't know what software you are using).
I don't see why your suggestion wouldn't be possible though, but I would carefully consider if it is an absolute requirement. There might be other, simpler, ways to achieve what you want.
One way of doing it would be to issue a token (JWT comes to mind) when logging in, and having the other services simply verify this token and extract the user data from it. This way no lookup of user data is required for authentication after the first login.
If shared state is what you need, I would suggest finding some existing software to handle the session storage. I see that for instance Redis has a solution for session management.
Also you may check out the answers to this question
When a user is interacting with a website, there's usually some object that could be considered the "current" object, like a shopping cart, or, to use an example in my world, a manufacturing job. What's the best practice for tracking that current object from page to page? I can think of a few:
put the ID as a request parameter (downside is security, since a
hacker could use that to change the URL to a different ID)
a session object (downside is if you have a huge amount of users
and/or the current object has a large memory footprint)
cookie? (Haven't tried that one)
Have I missed some obvious answer?
BTW, we're using Java, WebLogic and Struts1.
It really depends on your technology stack as to what "best practice" would be for you right now.
For example, if you're building a traditional Rails application using ERB templates without a MVC front end or anything, then I think that using the session object that the Rails framework provides for you would be best.
Most web frameworks will supply you an easy way to keep track of a particular user that's browsing the website. Most of the ones I've seen use a combination of your second and third options. They have a session ID that is stored as a cookie in the user's browser and every time that user sends a request to the web server, it loads a Session object from memory or the database using the session ID value that was stored in that cookie. Memory shouldn't be an issue unless you have an enormous number of users, but that also depends on the type of information that you're storing in there.
If you're storing entire database rows or records, and the sessions are being stored totally in memory, then maybe you should consider only storing the IDs to those records.
Research your particular web framework well to see how it handles user sessions.
As far as a cross-platform best practice, the Session object paradigm seems tot be the best approach to date. It permits matching of request parameters to tracking of sessions independent of the handling of the request parameter. An extension to this is that the Session object provides a handy place to put a collection of things for use if the session is re-identified (Java uses a Map).
Generally the Session is a representation of a single web browser visiting a single website repeatedly. Since there is nothing associating one request to another, this is generated synthetically from a combination of items, including user agent string, reply ip address, etc (in the past it was a stored value in a cookie, which caused no end to security issues).
Assuming you have a reliable Session object available, typically one stores the items that a supposed "single user" driving the session should have access to. So, if you have a shopping cart, it might be represented as a shopping cart object accessible from the session. In Java, that might be a map.
When identifying a new session
// request is a HttpServletRequest object in this example
if (request.getSession(false)) {
// must be a new one
Session newSession = request.getSession(true);
newSession.putValue("shoppingCart", new ShoppingCart());
}
Later on, when adding to the cart
ShoppingCart cart = (ShoppingCart)(request.getSession(false).getValue("shoppingCart"));
cart.addItem(item);
The benefits of separating out the detection from the request handling make it easy to fix / tweak session tracking without altering the code for the "session contents".
The other Answers are correct. Just a bit more explanation.
The Java Servlet technology’s Session object is indeed aimed at solving this exact problem, how to track a single user’s set of current objects over time, beyond the HTTP request-response lifecycle. This lends statefulness to an otherwise stateless protocol (HTTP). Every Servlet container (Tomcat, Jetty, WildFly, and so on) automatically handles the details such as using cookies or URL rewriting so you needn't worry about that.
Yes, as you add stuff to the Session object its memory usage grows in size. If running low on memory, your Servlet container such as Tomcat may choose to write an older Session object to storage using Serialization. The catch here is that all your objects in the Session must be serializable. Ensuring your classes (and all their nested objects) can correctly handle serialization can be a big chore.
Tip: If possible add memory to your server to more that handle your highest session load. As the wise man said, "Algorithms are for people who don’t know how to buy RAM.".
I am trying to learn more about JAVA web development. I am mainly focused on trying to understand how data that a user enters, maybe through the course of filling out a multipage form, is managed as the user moves from page to page.
From what I have gathered, you can store data within the session on the server side. I am also learning about cookies which are stored within the browser. Is there a general rule that is used to determine what data should be stored in a cookie vs. when you should store data in a session (session.setAttribute), or are these completely different concepts?
Thanks
The basics of session/cookies are like this.
A session is typically a way for a server to store data about a user. This can be done in a variety of ways from memory, file to database. This session can be used by you store pretty much anything you need to have as the user bounces around your site. It is assigned an ID (the session ID) which you don't usually need to worry about too much. In most web languages you can easily access the user session with some functions without dealing with IDs.
Now since the web is stateless - meaning there is really no way to know that user that visited page A is the same as the one that visited page B then we want to make sure that the user carries their session IDs with them. This can be done in a variety of ways but the most common one is through the use of a session cookie which is a special cookie automatically set by the server that is solely there for passing the session around. It can also be passed in the URL (I'm sure you've seen things like index.php?sessid=01223..) as well as headers and so on.
When most people talk about adding info to a cookie they are not talking about session cookies but about a custom cookie that you specifically set. The only reason that you would want to do that is if you needed to store info beyond the life of the session (which ends when the browser is closed). A good example of that is the "remember me" feature of many sites.
So use sessions unless you need to have something last a long time.
Yes. There are a few rules actually. For one, cookie data is sent by the browser on every request; session data is kept on the server (and not re-transmitted every request). However, usually the session id is used with a coookie. This enables the server to identify the client.
We can enable session by setting sessions-enabled to true in file appengine-web.xml. However, the session implemented by GAE is not persistent after closing browsers. My question is how to keep the session persistent so "remember me" function can be implemented. There are a number of Python libraries but I couldn't find any for Java. Thank you very much for your help!
The common way to do this is to associate a unique random key to your users, store it in a persistent cookie (use Cookie.setMaxAge() with the number of seconds you want this cookie to stay valid), and send this cookie to the user.
Look in the javadoc for HttpServletResponse.addCookie (to send a cookie to the user), and for HttpServletRequest.getCookies() (to get back the cookie from the client).
Since we can't mark a comment as an answer (and some people are likely to miss it entirely), I'll point out the specific solution per JB above. Get the session id using this.getThreadLocalRequest().getSession().getId(). Store the sid in a cookie as JSESSIONID with Cookies.setCookie(...)
This overwrites the cookie created by GAE, keeping the same session id, but applying your expiration time. Be careful how you use this, though, it's prone to attacks (look up session hijacking and XSS).
In the Java Servlet API, what is done to ensure that someone's session id is not stolen?
For example, if I had an active session and someone somehow get a hold of my session id, could they use it?
Nothing prevents it. You get the session ID, you can take part in the session.
In the usual case of cookies this is not a risk in itself. The attacker should not be able to read a user's session cookie unless:
they've got man-in-the-middle capability, in which case you've got much worse problems than just session IDs;
you've left a cross-site-scripting hole, in which case you've got much worse problems than just session IDs;
you're vulnerable to DNS-rebinding/cross-domain-cooking attacks, in which case you should fix it by only allowing known-good Host: requests.
(Whilst you can try tying sessions to IP addresses, this risks breaking valid sessions due to eg round-robin proxies. IPs can be used as part of a wider strategy for detecting suspicious activity, but on the public internet it's not a good idea always to require each request in a session to come from the same IP.)
Unfortunately in Servlet there is another case, apart from cookies: jsessionid= parameters. Since they appear in the URL itself, that makes them much more leaky (eg via referrers and pasted links). And that's far from the only practical problem with parameter session IDs. They mess up navigation and wreck SEO.
In my opinion jsessionid= URLs are one of Servlet's worst early mistakes, a discredited cookie fallback strategy from yesteryear that shouldn't be used for anything. But certainly they shouldn't be allowed to grant access to any privileged data; consider using HTTP Basic Authentication instead if you need a fallback mechanism for browsers that don't support cookies.
In Servlet 3.0 you can disable jsessionid= URLs easily using <session-config> in the web.xml; unfortunately in previous versions you are left mucking around with filters if you want to properly disable the feature.
Yes, they could use it. Nothing is done to protect it unless you put all your traffic over SSL.
This is how Firesheep works, which recently got a lot of attention for making session stealing easy.
Yes, the Session ID gives someone access to the corresponding session.
You could store the IP used during login in the session and when the IP changes require the user to login again.
Additionally (not sure if that's done automatically though) you could do the same for the User Agent - not really increasing safety against malicious attacks though, just against dumb users giving away their sessionid accidentally if it's passed via GET and not a cookie.