0

I've inherited a pretty ancient JSP application (JDK 1.3.1_15) and am attempting to plug a session fixation hole.

I'm successfully invalidating the current session after authentication using HttpSession.invalidate() however when the new session is created, the old session ID is re-used.

<%
// login.jsp
if (authenticated) {
    request.getSession().invalidate();

    // create new session and store data
    HttpSession session = request.getSession();
    session.putValue(...);
    // etc

    response.sendRedirect("logged-in.jsp");
    return;
}
%>

I can see the new session assignment in my HTTP monitor, it's just using the same number again.

-- Initial request response --
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=6a303082951311647336934;path=/

-- login.jsp request response --
HTTP/1.1 302 Moved Temporarily
Location: http://example.com/logged-in.jsp
Set-Cookie: JSESSIONID=6a303082951311647336934;path=/

Prior to me using session.invalidate() the second Set-Cookie response header was not present at all.

Does anybody have any advice on how to generate a new session ID? I'm not very familiar with JRUN4 but trawling through the configuration documentation hasn't turned up anything.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • Is it possible that some content is being written to the outputStream prior to the call to `session.invalidate()`? For example, anything outside of the scriptlet (`<%` and `%>`) tags? – matt b Jul 26 '11 at 02:57
  • @mattb Nope, already taken care of that issue. The new session is definitely created after the call to `invalidate()` – Phil Jul 26 '11 at 02:59
  • 1
    I'd just throw "JRUN" (or whatever it pretends to be for which I wouldn't expect much community support here) away and use a real and decent servletcontainer. Tomcat and Jetty are good and lightweight alternatives. Give it a try. Convince your manager about that. I know that this does technically not answer your question, but it's then also just a comment :) Good luck. – BalusC Jul 28 '11 at 03:57
  • @BalusC Not an option unfortunately – Phil Jul 28 '11 at 04:20

2 Answers2

3

To work around this, you can use a second non-persistent cookie to act as a session id that you can control the value of. The idea is to generate a unique id and store it in both the cookie and the session. Implement the same logic with this cookie that you are attempting to do with the session through using invalidate. Specifically, don't issue the actual identifier that will be accepted for future requests until authentication is successful. Then create a Servlet Filter that checks each request and matches the value of this new cookie to the value stored in the session. If they don't match, something nefarious is going on. I know it is a bit more cumbersome than just relying on session.invalidate() to issue a new id. But given your constraints and JRun's behavior, this will provide sufficient protection against session fixation.

laz
  • 28,320
  • 5
  • 53
  • 50
  • what if the client has disabled cookies? – hoipolloi Aug 01 '11 at 06:41
  • Then you would need to take the same approach of appending the id to the URL that occurs for JSESSIONID when cookies are disabled. The method `HttpServletRequest.isRequestedSessionIdFromURL()` can be used to determine if the session is managed via a cookie or appending. Then you'd need to create a utility to append the secondary session id to URLs. You would also need a Servlet filter as described here: http://stackoverflow.com/questions/962729/is-it-possible-to-disable-jsessionid-in-tomcat-servlet/962807#962807 except you would need to return the URL with the secondary session id too. – laz Aug 01 '11 at 11:41
  • 1
    This is a pretty sub-par container if we have to implement basic things like session handling ourselves. – hoipolloi Aug 01 '11 at 19:00
1

From Section 7.3 of the Java Servlet 3.0 specification, you can see that:

HttpSession objects must be scoped at the application (or servlet context) level. The underlying mechanism, such as the cookie used to establish the session, can be the same for different contexts, but the object referenced, including the attributes in that object, must never be shared between contexts by the container.

It's a really terrible idea, but I wonder if the JSESSIONID cookie is simply re-used and the actual session context destroyed. Can you still acess state (i.e. attributes) of the invalidated session?

hoipolloi
  • 7,984
  • 2
  • 27
  • 28
  • No, all session objects are unbound by the `invalidate()` call. It seems most other containers will assign a new ID for the new session, just not JRun – Phil Jul 29 '11 at 01:50
  • @Phil: Sure, because assigning a new ID makes the most sense. But it seems if JRun interprets the specification literally, there is no specific need to do so. – hoipolloi Jul 29 '11 at 01:53
  • 2
    @Phil: I just tried Tomcat 7.0.12 and WebSphere 7.0. They assign a new JSESSIONID immediately - have fun with JRun :-) – home Jul 31 '11 at 09:23
  • @hoipolloi: I disagree, this is a security issue. After login you may switch to HTTPS so you need a new ID, at least if the old one was transfered unsecured. – home Jul 31 '11 at 09:26
  • 1
    @home: where does it state that in the specification? Don't get me wrong, I'm not defending this implementation; merely trying to understand why JRun is doing such a counter-intuitive thing. – hoipolloi Jul 31 '11 at 21:14