Saturday 28 January 2012

Ghost in JSP Session

In my current project I'm using jboss 4.2.2 ga. As part of security implementation for my current project i had to work on adding HttpOnly flag. Initially I thought setting useHttpOnly in context.xml would server the purpose but later found out that, it was support only from JBoss 5 onwards. So we had to go ahead and do it via rewriting JSESSIONID value and setting it as a custom header. Then something strange happened. When we used HttpOnly the user sessions were getting shared. When one user changes session values it was getting reflected in another user's browser. Like changing the language in one changed the language of another.

After much debugging and researching i found out that the issue was not with http only attribute but it was a logical error in setting the header. When a log out occurred we invalidated the session and routed the request via /forms/index.jsp. This flow cleared the http only flag and javascript was able to access the cookie entries. So as a workaround we added the following header in /forms/index.jsp

response.setHeader("SET-COOKIE", "JSESSIONID=; Path=" + request.getContextPath() + "; HttpOnly");

This was the culprit. Here what happened is that the JSESSIONID was cleared or set to empty. So, who ever passes thru index.jsp via a logout or error will get a JSESSIONID of null. As a result all these users will have empty (same) jsession id. this causes the sharing. So when one person changes the language it reflects to another. Luckily the fix was simple. Just change the header to

response.setHeader("SET-COOKIE", "JSESSIONID=" + request.getSession(true).getId() + "; Path=" + request.getContextPath() + "; HttpOnly");

This will prevent javascript from accessing the cookie also doesn't causes session sharing.

Setting HttpOnly in JBoss



HttpOnly is an additional flag included in a Set-Cookie HTTP response header. Using the HttpOnly flag when generating a cookie helps mitigate the risk of client side script accessing the protected cookie (if the browser supports it).

The example below shows the syntax used within the HTTP response header:

Set-Cookie: <name>=<value>[; <Max-Age>=<age>]
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; HttpOnly]

If the HttpOnly flag (optional) is included in the HTTP response header, the cookie cannot be accessed through client side script (again if the browser supports this flag). As a result, even if a cross-site scripting (XSS) flaw exists, and a user accidentally accesses a link that exploits this flaw, the browser (primarily Internet Explorer) will not reveal the cookie to a third party.

More details on HttpOnly can be found here


Until JBoss 5 the application server doesn't give any configurations so as to set HttpOnly. However we can do it programatically. Below are the ways by which HttpOnly flag can be set in different versions of Jboss servers.

JBoss 4

Rewrite JSESSIONID value using and setting it as a custom header

String sessionid = request.getSession().getId();
response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; HttpOnly"); 


JBoss 5 & 6

Set useHttpOnly=True in context.xml. The context.xml can be found in jboss/server/<myserver>/deploy/jbossweb.sar/context.xml

Add the following line to context.xml

<SessionCookie secure="true" httpOnly="true" />

JBoss 7
Add the http-only tag to session config in web.xml

<session-config>
    <cookie-config>
        <http-only>true</http-only>
        <secure>true</secure>
    </cookie-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>