Go...
Welcome
Feeds
JSESSIONID considered harmful
Posted by ccondit on 10/19/06 @ 2:33 PM :: Updated by ccondit on 7/2/09 @ 6:15 PM
Tags :: :: :: ::

One little-known feature of the Java Servlet Spec allows for encoding session identifiers in URLs. In theory, this allows browsers without support for cookies to maintain session state with your website. In practice, however, there are several problems with this approach:

Every link on your site needs manual intervention

Cookieless sessions are achieved in Java by appending a string of the format ;jsessionid=SESSION_IDENTIFIER to the end of a URL. To do this, all links emitted by your website need to be passed through either HttpServletResponse.encodeURL(), either directly or through mechanisms such as the JSTL <c:out /> tag. Failure to do this for even a single link can result in your users losing their session forever.

Using URL-encoded sessions can damage your search engine placement

To prevent abuse, search engines such as Google associate web content with a single URL, and penalize sites which have identical content reachable from multiple, unique URLs. Because a URL-encoded session is unique per visit, multiple visits by the same search engine bot will return identical content with different URLs. This is not an uncommon problem; a test search for ;jsessionid in URLs returned around 79 million search results.

It's a security risk

Because the session identifier is included in the URL, an attacker could potentially impersonate a victim by getting the victim to follow a session-encoded URL to your site. If the victim logs in, the attacker is logged in as well - exposing any personal or confidential information the victim has access to. This can be mitigated somewhat by using short timeouts on sessions, but that tends to annoy legitimate users.

What you can do

For the vast majority of web sites, requiring cookies to store session state is not a major problem. It is probably safe to disable URL-based sessions entirely. At a bare minimum, session identifiers need to be hidden from search bots to avoid the repercussions detailed above. Unfortunately, the servlet spec does not provide a standard way to disable the use of URL-based sessions and many servlet containers do not provide a mechanism to disable them either.

The solution is to create a servlet filter which will intercept calls to HttpServletRequest.encodeURL() and skip the generation of session identifiers. This will require a servlet engine that implements the Servlet API version 2.3 or later (J2EE 1.3 for you enterprise folks). Let's start with a basic servlet filter:

package com.randomcoder.security;

import java.io.IOException;

import javax.servlet.*;
import javax.servlet.http.*;

public class DisableUrlSessionFilter implements Filter
{
  public void doFilter(
      ServletRequest request,
      ServletResponse response,
      FilterChain chain)
  throws IOException, ServletException
  {
    // TODO add filter logic here
  }

  public void init(FilterConfig config)
  throws ServletException {}

  public void destroy() {}
}

We don't need to be concerned with the init() and destroy() methods; let's focus on doFilter(). First, let's exit quickly if for some reason the current request is non-HTTP, and cast the request and response objects to their HTTP-specific equivalents:

if (!(request instanceof HttpServletRequest))
{
  chain.doFilter(request, response);
  return;
}

HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;

Next, let's invalidate any sessions that are backed by a URL-encoded session id. This prevents an attacker from generating a valid link. Just because we won't be generating session-encoded links doesn't mean someone else won't try:

if (httpRequest.isRequestedSessionIdFromURL())
{
  HttpSession session = httpRequest.getSession();
  if (session != null) session.invalidate();
}

To disable the default URL-encoding functionality, we need to wrap the existing HttpServletResponse object. Fortunately, the Servlet API provides just such a class ready-made in HttpServletResponseWrapper. We could subclass it to provide our own handling, but this is a trivial enough change that an anonymous inner class will do nicely:

HttpServletResponseWrapper wrappedResponse
    = new HttpServletResponseWrapper(httpResponse)
{
  public String encodeRedirectUrl(String url) { return url; }
  public String encodeRedirectURL(String url) { return url; }
  public String encodeUrl(String url) { return url; }
  public String encodeURL(String url) { return url; }
};

You may notice that we have overridden four methods, not one. encodeRedirectURL is used to encode redirected URLs, which can sometimes require different logic to determine if session identifiers are required. The other two methods are deprecated, but are included here for completeness.

Finally, we need to pass the original request and our response wrapper to the next filter in the chain:

chain.doFilter(request, wrappedResponse);

Our servlet filter is now written, but we still need to tell our servlet container about it. For this, we need to add the following to web.xml:

<filter>
  <filter-name>
    DisableUrlSessionFilter
  </filter-name>
  <filter-class>
    com.randomcoder.security.DisableUrlSessionFilter
  </filter-class>
</filter>

...

<filter-mapping>
  <filter-name>DisableUrlSessionFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

This registers our filter with the servlet container, and maps it to all requests. For best results, the filter mapping should be placed above any other filter mappings to prevent any calls to encodeURL from slipping through.

Resources

Update: This site offers some additional advice using mod_rewrite. Thanks, Darren!

Update: Fixed reference to encodeUrl(). As pointed out below, this is found in HttpServletResponse, not HttpServletRequest.

SessionTrackingFilter
Posted by Dan Allen on 11/6/06 @ 4:19 PM :: #2
I proposed a solution to the portable URL problem that encode URLs introduce. It is available on my blog.

http://www.mojavelinux.com/blog/archives/2006/09/improved_session_tracking/
Can be secure ...
Posted by Cameron Purdy on 11/7/06 @ 7:33 AM :: #3
Regarding security, spoofing has two sides: Trying to find a legitimate JSESSIONID, and trying to use someone else's existing JSESSIONID.

The first (in a reasonable implementation) is no more difficult than breaking any cryptographic code. For example, a 16-character JSESSIONID employing just A-Z, a-z and 0-9 provides 47,672,401,706,823,533,450,263,330,816 combinations, meaning that with one million logged on users (i.e. one million legit JSESSIONIDs that could be found) and an attack rate of 100 unique JSESSIONIDs per second, it would take over seven trillion years on average to find a legitimate JSESSIONID.

The second (again, in a reasonable implementation) should be prohibited based on other characteristics of the client connection, such as the IP address. While IP spoofing is theoretically possible, the ability to both grab a JSESSIONID while it is valid _and_ spoof an IP address is a pretty big task.

The exception is when the attacker is behind the same NAT firewall as the victim, in which case the ability to grab a JSESSIONID is likely easy _and_ the IP address of the attacker is automatically the same IP address as the victim. There is no way to protect against this case except by explicitly requiring a persistent HTTPS connection in concert with the use of JSESSIONID.

As a general rule of thumb, it is good to default to cookies, and only switch to JSESSIONID URL encoding when cookies are not supported, and only if the above considerations (and those listed elsewhere in this thread) do not apply.

Peace,

Cameron Purdy
Re: Can be secure...
Posted by ccondit on 11/7/06 @ 8:15 AM :: #4
You are correct that cryptographically, JSESSIONID can be secure. However, servers usually don't require an IP address along with the session ID because large groups of users with the same IP address are not uncommon (think AOL proxies).

I believe URL-based sessions are an abuse of the URL specification and cause more problems than they solve.
jsessionid is a fallback for when cookies are unsupported
Posted by Porter on 11/7/06 @ 12:19 PM :: #5
My understanding is that jsessionid has always been a fallback for browsers which do not support (or have support for turned off) cookies. Java technologies like Struts have employed them in that fashion.

In short the intent behind jsessionid is to provide a backup so that the web application can still function correctly even when a feature not under the developer's control is rendered unavailable. You may believe that they cause more problems than they solve - however they solve the largest problem that any user of your site might encounter which is your application not working _at all_ without them changing either their browser, or browser settings. Are they really willing to do that for your site? Or are they just going to wander off thinking, "gee it seemed like that site would be cool, but it didn't work."
Re: jsessionid is a fallback for when cookies are unsupported
Posted by ccondit on 11/7/06 @ 1:27 PM :: #6
You are correct regarding the *intended* purpose of jsessionid. However, I believe that purpose has not been achieved with the current implementation.

Spiders (such as Google) typically do not support cookies and so by default, the server will append a session token to all session-enabled URLs sent to spiders. I didn't cover this approach in the article, but you could modify the code to only hide session identifiers from known bots (using user-agent sniffing). This would be a bit more fragile, but would address your concern that we need a fallback for "cookie-challenged" browsers.

By far the most common use for cookies is to enable logins to a site, and if necessary, this can be enabled with BASIC authentication for simple clients. As with any good web site, things should degrade whenever possible.
Mod Rewrite
Posted by Darren on 1/8/07 @ 8:58 AM :: #10
Hi, this is very useful - I've got it working on my site now.
I also added something to strip incoming jsessionid links from Google etc using mod rewrite.

Details on my blog: http://boncey.org/2007_1_8_purging_jsessionid
software engineer
Posted by arpit on 1/8/07 @ 12:32 PM :: #11
hi
i have tried u r above given filter .
but this is not working for me :-(.
i have also added session=false on jsp page.
but then too i have same jsessionId...
can u please let me know how do i configure this
solution.

and i feel
HttpSession session = httpRequest.getSession();
if (session != null) session.invalidate();
this will disable http session forever so i guess filter should be called for static pages only
Configuring the filter
Posted by ccondit on 1/24/07 @ 4:19 PM :: #17
arpit,

If the filter is not working for you, it is possible that you have not configured it in web.xml. Try modifying the filter adding debugging statements. If you don't see any output, the filter is probably not being executed.

As for the session invalidation logic, that only fires if the current request has a URL-encoded identifier, so it won't affect any normal URLs.

Best of luck.
Re: Mod Rewrite
Posted by ccondit on 1/24/07 @ 4:39 PM :: #18
Darren,

Glad to hear this was useful to you. Excellent follow-up article by the way -- I think you've discovered the missing piece to the JSESSIONID "puzzle".
Protected sessions
Posted by Dmitry on 7/6/07 @ 6:41 AM :: #1513
This filter http://www.servletsuite.com/servlets/protectsessionsflt.htm
checks the IP address too
Architect
Posted by Techcool on 7/26/07 @ 10:24 AM :: #1589
I have implemented this to get rid of JSESSIONID from URL string, however this seems have no impact on secured links in my site. I am not sure why secured links still contain JSESSIONID in url links.
Redirect from within filter
Posted by Bjoern on 10/13/07 @ 10:23 AM :: #2001
Many thanks for that helpful article, it saved me a lot of time!

I have copied your filter, and I also redirect the old urls for purging from within the filter:

//redirect to URL without jsessionid,
StringBuffer url = httpRequest.getRequestURL();

String queryString = httpRequest.getQueryString();

String redirectURL = url+(StringUtils.isNotEmpty(queryString) ? "?"+queryString : "");

wrappedResponse.setHeader(HEADER_LOCATION, redirectURL);
wrappedResponse.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
return;

However, I have not really dug into the HTTP specification very deeply. THis seems to work, but no idea if it is 100% correct. Also the
httpRequest.isRequestedSessionIdFromURL()

thing seems a bit unreliable: I think it only works if the client has stated that it doesn't accept cookies? Good enough for the search engines, but not for the hackers. But I found no other way to identify URLs with jsessionid, as the jsessionid doesn't show up in the parameters of HttpServletRequest.
An alternative to secure the URL.
Posted by SecurityMinded on 1/10/08 @ 3:44 PM :: #2918
"an attacker could potentially impersonate a victim by getting the victim to follow a session-encoded URL to your site. If the victim logs in, the attacker is logged in as well "

If the application does not generate the session until AFTER a person has been authenticated, then an attacker should not be able to get the user to folllow a session-encoded URL which would have them log in.
Mr
Posted by Guy Greenblat on 1/29/08 @ 11:10 AM :: #3016
Hi all

I have tried using this filter and get the following message from the browser when cookies are disabled "This problem can sometimes be caused by disabling or refusing to accept cookies." any suggestions? This is the only filter in the web.xml. The framwork we are using is Spring webflow.

We have also tried http://tuckey.org/urlrewrite/ with no success.

Any help would be appreciated.
Regarding Servlet Filter is not working on my server
Posted by karthik on 3/21/08 @ 6:55 AM :: #3469
Hi,

Here above mentioned coding deployed in my application.but its not have more impact which JsessionID still exist.Actually i am using weblogic server which not take in account of filter coding,so please come up with more answer for this query and should i implement Servlet-api.jar file which 2.3 version file for this coding .

with regards
Karthik
above Servlet filter coding
Posted by karthik on 3/21/08 @ 7:00 AM :: #3470
Hi,

The Above codin what kind of method can i add it to hide jsessionid in url passing
with regards
Karthik
session
Posted by santosh on 7/26/08 @ 4:08 AM :: #4161
i entered into login page in next page i want to change user details without enter into login id in this page i think we can set the session id for login page only please give the code
Little mistake
Posted by Juan on 8/13/08 @ 9:17 AM :: #4218
Great article, thanks for the help.

Just to say this: the method encodeURL() is actually in the object HttpServletResponse.
Not in the request, like the section "Every link on your site needs manual intervention" says.
Saved Me a Ton of Work
Posted by Robert Fischer on 9/6/08 @ 9:01 AM :: #4858
I was about to rewrite your work, and this blog post saved me all that hassle. I didn't even have to dredge up my old Servlet API spec experience, and your comments let me still know what was going on. Excellent -- thank you!

BTW, can you officially release this work under some kind of non-GPL license? I'd like to package up your filter for a Grails plugin.
small error in second paragraph
Posted by gc on 10/24/08 @ 9:22 AM :: #5045
second paragraph:

HttpServletRequest.encodeURL()

=>

HttpServletResponse.encodeURL()
Great Article!
Posted by Sethu on 12/8/08 @ 12:40 PM :: #5471
Let me digest and give more update.
JSessionID vs cookie
Posted by Dano on 1/17/09 @ 2:41 PM :: #5853
I understand the argument that jsessionid is bad for search engines. However from the security point of view of using a cookie vs jsessionid I do not grok. The jsessionid is some 'encrypted' magic data value that the server uses to identify the session. If we rip this out..then the application will still need to inject some magic encrypted number into the cookie. As such wouldn't hackers be able to see the cookie as well? with the magic value? as such as a hacker if I would able to obtain the jsessionID by 'sniffing' requests on the network..I would still be able to obtain the cookie in the same way...or am I missing something?
Rubbish
Posted by Andrew Lovell on 1/28/09 @ 7:56 AM :: #5931
Sorry but any self-respecting hacker that intends to do harm can just as easily capture the cookie as he can capture the url of the request. There is no perfect solution without encrypting the whole communication as with https. Anything short of this is an act of futility.
Isnt this confusing the purpose of session management?
Posted by Maruthi Kumar on 4/16/09 @ 10:13 AM :: #6398
Folks,

JSessionId or cookies are to authenticate or understand a client and its session, and that is the purpose of having either of them for a web or app server. If we are confusing that we wouldnt want to have JSessionId isnt it destroying the actual purpose of authenticating a session by the app server??
Load Balancer & JSession ID
Posted by Nik on 6/18/09 @ 12:00 AM :: #6901
Really good article.

I have only one question. I am using 2 tomcat & using apache as a load balancer. if I removed jsession id then how it will definitely breaks & 2 different sessions will starts in two nodes. Other thing we are using secure & non-secure one. Now I have to create session in non-secure url so the session can move to secure one.
Session Hijacking
Posted by Darrell Teague on 7/6/09 @ 12:49 PM :: #7099
Good posting but a lot of this misses the point about malware and protection. What one really must do since HTTP is stateless and some moniker is needed to convey the session-id/state is to PROTECT the moniker, whether in a cookie or the URL, etc. I developed a product that encrypts the JSESSIONID using RSA and includes meta-data checkng like a hash of the value to check for tampering, a machine-identifier so the cookie/URL cannot be exported/imported into another machine for impersonation, etc.
So while the author is right in that putting this very sensitive moniker in plain-text in the URL is dangerous, remember that it is the fact that the moniker is plain-text, in any form, is the problem. SSL won't help you in a MITM attack, if there is malware on the end-point, etc... the application must encrypt the moniker.
Hope this helps.
Cheers.
-Darrell Teague-
Subayai Inc.
Looks liike google has come to the party for the Servlet Container spec
Posted by golfman on 10/3/09 @ 11:17 AM :: #8488
Doing a search for
inurl:jsession
used to return 235,000,000 entries but nowadays it returns less than 20,000 and I can't see any of the jsession format specified in the servlet container spec.

This leads me to believe that google has taken advantage of the fact that ALL web apps running in servlet containers use the same parameter 'jsession' and so it google can uniformly deal with that in a good way.
Chief Architect
Posted by Darrell Teague on 10/16/09 @ 2:43 PM :: #8604
Certain cookie IDs are static. For J2EE, the ID is indeed "jsessionid". For ASPNET's default session provider, it is "ASP.NET_sessionId" but this is customizable in the latest releases (though most developers use the default provider and never override this name). In any case, cookies are simple string key/value pairs so the value is just text (could be base64-encoded cipher text). The fact that the session id moniker is well-known doesn't matter - though it could play a part in the extent to which a general purpose attack is effective (e.g., your application would not be suspectible if you changed the name but if they targeted your app, then it would be no different in effect).
No 404 page if url not found
Posted by Torsten Uhlmann on 9/25/10 @ 10:03 AM :: #12715
Thanks for this great post.

I have a small recommendation: Initially I tried to open the link "http://randomcoder.com/articles/jsessionid-considered-" because of a line break in the email that contained it and received a pretty horrible servlet container exception.

Just to let you know,
Torsten.
This is abundant recource I like itt thank you
Posted by Nombadams on 6/21/11 @ 3:27 PM :: #16108
Hello all! I like this forum, i found tons inviting people on this forum.!!!

Large Community, respect all!
How to Erase JSessionId from URL
Posted by jack on 7/8/11 @ 12:59 AM :: #16335
Hi,

I am using ATG9.1 and trying to create clean url for the bots. I am able to do that using catalog item link droplet but it get appended with ugly JSessionId. I tried the code given above to avoid encoding of url but no luck. I am using Jboss-EAP-4.2 with ATG9.1.

I have created my custom filter java class using above code and added the same in web.xml.
But i am still seeing JSessionId is appending in my clean urls.

Any one has any clue about the same?

Thanks & regards,
Jack
Need help implementing this
Posted by Al on 11/8/11 @ 2:39 PM :: #19132
Is there anyone that can implement this for me.
Made up arguments do not strengthen a case
Posted by Don Kongo on 2/28/12 @ 10:26 AM :: #22933
"Because the session identifier is included in the URL, an attacker could potentially impersonate a victim by getting the victim to follow a session-encoded URL to your site. If the victim logs in, the attacker is logged in as well - exposing any personal or confidential information the victim has access to."

This is clearly a completely made-up argument. SEO fine, ugliness of URLs fine, but don't pretend it's about security. Nothing like this is possible and for any situation not involving the user actively copy/pasting the URL to an attacker (and with very lax other security) there is no difference in having that data in a cookie, since that data is also easily and readily available if the URL is.

Ok?
Session tracking in Servlet 3.0
Posted by Ivan Yatskevich on 4/18/12 @ 10:24 AM :: #25097
In Servlet 3.0 it's possible to configure session tracking mechanism. I've written a short howto here -
http://weblog.yatskevich.com/post/21326120441/session-tracking-in-servlet-3-0
Comment on this article

Comments are closed for this post.