You are on page 1of 9

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
y y DisableUrlSessionFilter.java web.xml

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 06/11/06 @ 15:19 :: #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 07/11/06 @ 06:33 :: #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 07/11/06 @ 07:15 :: #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 07/11/06 @ 11:19 :: #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 07/11/06 @ 12:27 :: #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 08/01/07 @ 07:58 :: #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 08/01/07 @ 11:32 :: #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 24/01/07 @ 15:19 :: #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 24/01/07 @ 15:39 :: #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 06/07/07 @ 04:41 :: #1513

This filter http://www.servletsuite.com/servlets/protectsessionsflt.htm checks the IP address too Architect


Posted by Techcool on 26/07/07 @ 08:24 :: #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 13/10/07 @ 08:23 :: #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 10/01/08 @ 14:44 :: #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 29/01/08 @ 10:10 :: #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 21/03/08 @ 04:55 :: #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 21/03/08 @ 05:00 :: #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 26/07/08 @ 02:08 :: #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 13/08/08 @ 07:17 :: #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 06/09/08 @ 07:01 :: #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 24/10/08 @ 07:22 :: #5045

second paragraph: HttpServletRequest.encodeURL() => HttpServletResponse.encodeURL() Great Article!


Posted by Sethu on 08/12/08 @ 11:40 :: #5471

Let me digest and give more update. JSessionID vs cookie


Posted by Dano on 17/01/09 @ 13:41 :: #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 28/01/09 @ 06:56 :: #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 16/04/09 @ 08:13 :: #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 17/06/09 @ 22:00 :: #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 06/07/09 @ 10:49 :: #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 TeagueSubayai Inc. Looks liike google has come to the party for the Servlet Container spec
Posted by golfman on 03/10/09 @ 09:17 :: #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 16/10/09 @ 12:43 :: #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). http://www.mbtgoods.com
Posted by Mbt anti-shoes on 13/05/10 @ 01:13 :: #9691

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. http://www.mbtshoesfactory.com No 404 page if url not found
Posted by Torsten Uhlmann on 25/09/10 @ 08:03 :: #12715

Thanks for this great post. I have a small recommendation: Initially I tried to open the link "http://randomcoder.com/articles/jsessionidconsidered-" 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. Online game
Posted by Vedasinousano on 13/02/11 @ 16:15 :: #14105

< a href=tehnogame.ucoz.ru> RPG , , . , . , -, .</a> ghd hair


Posted by Lisseurs Cheveux on 19/02/11 @ 01:52 :: #14226

Le nouveau con u Lisseurs Cheveux est un outil de style unique et ultime pour les cheveux courts la fois les hommes et les femmes.
Posted by popugai on 06/05/11 @ 23:41 :: #15559

-8 . 8 000 .
Posted by popugai on 11/05/11 @ 14:08 :: #15608

. . : , , , , . This is abundant recource I like itt thank you


Posted by Nombadams on 21/06/11 @ 13:27 :: #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 07/07/11 @ 22:59 :: #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 08/11/11 @ 13:39 :: #19132

Is there anyone that can implement this for me.

handbags party purse


Posted by duagemelonie on 09/12/11 @ 07:56 :: #19816

click to view <a href=http://www.large-handbags.net/buy-purses-designer-party-fake-handbags-ezp-5.html>bag party</a> , just clicks away <a href=http://www.large-handbags.net/buy-purses-designer-party-fake-handbagsezp-5.html>bags party</a> at my estore kazadereza
Posted by Potomuchto on 09/12/11 @ 08:31 :: #19825

<a href="http://todaynotion.com/deliteli_moshhnosti_kak_attenyuator4.html"></a>
6072 moderated comments not displayed.

Comment on this article

You might also like