By default tomcat will create a session cookie for the current domain.
If you are on www.example.com, your cookie will be created for www.example.com (will only work on www.example.com). Whereas for example.com it will be created for .example.com (desired behaviour, will work on any subdomain of example.com as well as example.com itself).
I've seen a few Tomcat valves which seem to intercept the creation of session cookies and create a replacement cookie with the correct .example.com domain, however none of them seem to work flawlessly and they all appear to leave the existing cookie and just create a new one. This means that two JSESSIONID cookies are being sent with each request.
I was wondering if anybody has a definitive solution to this problem.
This is apparently supported via a configuration setting in 6.0.27 and onwards:
Configuration is done by editing
META-INF/context.xml
<Context
sessionCookiePath="/something"
sessionCookieDomain=".domain.tld" />
https://issues.apache.org/bugzilla/show_bug.cgi?id=48379
I have just gone through all of this looking for a simple solution. I started looking at it from the tomcat perspective first.
Tomcat does not give direct access to configuring the domain cookie for the session, and I definitely did not want to custom patch tomcat to fix that problem as shown in some other posts.
Valves in tomcat also seems to be a problem solution due to the limitations on accessing headers & cookies built into the Servlet specification. They also fail completely if the http response is commited before it gets passed to your valve.
Since we proxy our requests through Apache, I then moved onto how to use apache to fix the problem instead.
I first tried the mod_proxy directive ProxyPassReverseCookieDomain, but it does not work for JSESSIONID cookies because tomcat does not set the domain attribute and ProxyPassReverseCookieDomain cannot work without some sort of domain being part of the cookie.
I also came across a hack using ProxyPassReverseCookiePath where they were rewriting the path to add a domain attribute to the cookie, but that felt way to messy for a production site.
I finally got it to work by rewriting the response headers using the mod_headers module in apache as mentioned by Dave above.
I have added the following line inside the virtual host definition:
Header edit Set-Cookie "(JSESSIONID\s?=[^;,]+?)((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(;\s?(?:(?i)Domain\s?=)[^;,]+?)?((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(,|$)" "$1$2; Domain=.example.com$4$5"
The above should all be a single line in the config. It will replace any JSESSIONID cookies domain attribute with ".example.com". If a JSESSIONID cookie does not contain a domain attribute, then the pattern will add one with a value of ".example.com". As a bonus, this solution does not suffer from the double JSESSION cookies problem of the valves.
The pattern should work with multiple cookies in the Set-Cookie header without affecting the other cookies in the header. It should also be modifiable to work with other cookies by changing JSESSIONID in the first part of the pattern to what ever cookie name you desire.
I am not reg-ex power user, so I am sure there are a couple of optimisations that could be made to the pattern, but it seems to be working for us so far.
I will update this post if I find any bugs with the pattern. Hopefully this will stop a few of you from having to go through the last couple of days worth of frustrations as I did.
As a session (and its Id) is basically considered of value only for the issueing application, you may rather look for setting an additional cookie. Have a look at Tomcats SingleSignOnValve, providing the extra-Cookie JSESSIONIDSSO (note the ...SSO) for the server path "/" instead of "/applicationName" (as JSESSIONID cookies are usually set).
With such a Valve you may implement any interprocess communication you need in order to synchronize any state between different servers, virtual hosts or webapps on any number of tomcats/webservers/whatever.
Another reason why you cannot use tomcats session cookie for your own purposes is, that multiple webapps on the same host have different session ids. E.g. there are different cookies for "/webapp1" and "/webapp2". If you provide "/webapp1"'s cookie to "/webapp2", this wouldn't find the session you referenced, invalidate your session+cookie and set its own new one. You'd have to rewrite all of tomcats session handling to accept external session id values (bad idea securitywise) or to share a certain state among applications.
Session handling should be considered the containers (tomcats) business. Whatever else you need you should add without interfering with what the container believes is necessary to do.
I've run into this at $DAYJOB. In my case I wanted to implement SSL signon then redirect to a non SSL page. The core problem in tomcat is the method (from memory) SessionManager.configureSessionCookie which hard codes all the variables you would like to get access to.
I came up with a few ideas, including a particularly egregious hack using mod_headers in apache to rewrite the cookie based on regex substitution.
The definative way to solve this would be to submit a patch to the tomcat developers that adds configurable parameters to the SessionManager class.
The valve techniques do not seem to be 100% perfect. If you dare to modify Tomcat itself:
catalina.jar contains the following class: org.apache.catalina.connector.Request
The Request has a method:
configureSessionCookie(Cookie cookie)
For our environment it was best to just hardcode it, but you could do more fancy logic:
cookie.setDomain(".xyz.com");
Seems to work perfectly. Would be nice if this was configurable in tomcat.
Related
I've been tasked with modifying an application, of which I have access to the XML configuration of it in what appears to be Tomcat 7.
I need a cookie (called oname to be specific) shared to another domain (example.com). That is to say that, an iframe on the application to example.com can share the cookies from the application.
First of all, is this possible? Second of all, if it is (which I hope it is! :)) how can I do it via XML and XML only (referring to the configuration files found in the base of the application).
I've done some research on cookies, and I determined I need to modify the domain section on all cookies. If I need to change change all cookies globally (e.g. adding an XML element within the configuration to add domain = example.com to all cookies then that's acceptable!
I've pretty much have 2 options:
Find a specific XML element to change all cookies globally to add my desired domain
Have a JavaScript shim on the client side (I have access to the HTML also) wrap around the normal method to set cookies, while also adding example.com to the domain bit on the cookies.
Thanks for any help!
If your application is running on www.example.com, it can set a cookie for .example.com, but not if it's running on any other domain than example.com. If it would be possible to set cookies for unrelated domains, Anybody could easily set a cookie for any other random site, and as cookie names are typically well predictable, interfere with those sites (e.g. setting jsessionid or other session- and identification cookies in a rogue way).
Your only option is if the other site cooperates and provides a URL that you can redirect to which sets the cookie itself. Beware: Without checking the validity of the request, anybody can redirect to that site and set a cookie through the same measures - you can easily introduce a security issue.
My fiddler trace looks like this:
Cookie / Login
C.LWSN=BLNCUJBMUyCAiyVztlU7fREOpDjFC4!2FUUmPJ1UTPUhWyQUl7gVFdMAAAAVbfn6pI
JSESSIONID=0000Fbsp0QmvTif-1v6OFxIEz7y;
JSESSIONID=0000s2dD67nvl5G5pScW2cjYk0j:-1;
KBJEILKHOJUWIOR2=MXQPuA6gDQMsi8ODwICE5Z9mKX7lShmIt5k0p6cbJ6I=;
Is it normal for my fiddler trace to contain two JSESSIONID?
Anyone knows what is causing this?
Multiple JSESSIONID entries in the HTTP header is not unusual. Sometimes it is when the user has failed over from one cluster member to another. Sometimes it could be the previous JSESSIONID expired and the user picked up a new one (very code dependent so would need more detail). Behavior is version dependent and those cookie values look like they come from an older version of WAS. There is more detail if you google websphere multiple jsessionid cookies
I have two applications running in Jboss, can I write a cookie in a application and read in another?
For example, if I have two Servlets:
- WriterCookieServlet on localhost:8080/Application1
- ReaderCookieServlet on localhost:8080/Application2
WriterCookieServlet:
Cookie cookie = new Cookie("cookie", "cookieValue");
response.addCookie(cookie);
response.sendRedirect("localhost:8080/Application2");
Then on ReaderCookieServlet I want read this cookie.
I think #galuano1 is right: this should indeed be possible. Make sure the path is correct, though. It is used to determine whether a certain cookie is visible to a web-application.
From the Cookie Javadoc:
The cookie is visible to all the pages in the directory you specify, and all the pages in that directory's subdirectories. A cookie's path must include the servlet that set the cookie, for example, /catalog, which makes the cookie visible to all directories on the server under /catalog.
Consult RFC 2109 (available on the Internet) for more information on setting path names for cookies.
I'd say you should use / for directory, since both applications will have a different context root.
As long as the domain specified in the cookie is same ( here localhost ) , cookie can be read by the two different applications
It is true: cookie can thoerically be read by the application if it comes from the same domain. This mean that the application has it available, it doesn't imply the application has available the secrets needed to interpret it
The problem here may not be related to the theorical part but on the technology part: if the cookie is not in clear text (as it should be) it requires to be opened by the target application who needs to read the content
This usually comes out of the box if the application which forge the cookie is the same application that needs to read it.
But if it is forged by an application 1 and needs to be decrypted by an application 2, you need to ensure this command you used:
Cookie cookie = new Cookie("cookie", "cookieValue");
doesn't use any application specific secret to encrypt the cookie, otherwise it can never be opened by a different application.
Of course the answer may change according the technology you are using, don't know the behaviour in Java, I am aware many technologies to use machine based secrets to encrpyt and sign the cookie.
I'm looking for a plain English, "for dummies" explanation of how does JSESSIONID work from security aspects
Can someone who merely knows my current JSESSIONID impersonate / hijack my session?
In what scenarios JSESSIONID will be part of the URL, and is this OWASP #2 security risk (scenario #1) still relevant for latest versions of Tomcat / Glassfish, and if so, what to "turn off/on" to prevent it?
Q: Can someone who merely knows my current JSESSIONID impersonate / hijack my session?
A: Yes.
That's why it is important that your site is careful with cookies. Indeed, if you are worried about packet sniffing, this means that you should only send the session cookie when the request was made over an HTTPS connection1. And setting the 'httpOnly' flag helps things by stopping client-side javascript, etc from using the cookie.
Q: In what scenarios JSESSIONID will be part of the URL
A: Typically, this happens when the webserver (at the container level) puts the session token into the URL:
as a workaround for the user's browser not setting cookies, or
to make the URL "suitable" for bookmarking or sending to someone else via an email.
Obviously, this is insecure and "bad practice" ... though a short session timeout does tend to mitigate this. (Alternatively, it is OK over HTTPS ... provided that the user doesn't share the URL with other people1.)
For Tomcat 6.x, I believe that the way to prevent the container from (ever) adding the session id to the URL is to add the disableURLRewriting="false" attribute to the context.
For Tomcat 7:
Context.disableURLRewriting: This has been removed. An equivalent effect can be obtained by configuring the session-config/tracking-mode elements in a web application or in the global CATALINA_BASE/conf/web.xml file.
1 - This assumes that you have patched (etc) your webserver to address the known SSL end-point vulnerabilities. If not, your HTTPS connections may be insecure.
I have a java applet that needs to do http requests to the server. A quick experiment showed that the session id cookies from the browser is not sent along, so i'll have to set it manually.
Currently, I see 2 possible solutions:
somehow get hold of the cookie data from within the applet
pass the cookie information into the applet's contructor via javascript
I'd prefer the first solution, but i wasn't able to find a working solution for that. all information i found (mostly netscape.javascript.JSObject) were outdated (my 1.5 VM does not have this class)
Any great ideas or resources i have not yet found?
Are you sure your JVM doesn't contain this class? You should look in $JAVA_HOME/lib/plugin.jar. I found it in my 1.5.0_14 installation.
If you are generating the page dynamically, you don't necessarily need to use JavaScript to communicate the session ID. As long as you know it server-side, you can place it into an applet parameter tag in the generated HTML which contains the <applet> tag.
Nowadays all browsers are supporting httponly cookies.If cookies are consciously set in server as 'httponly' in appropriate response headers,applets may not be able to access it.