J2EE Sessions in CF10 Uses Secure Cookies

April 05, 2013
coldfusion

This week I helped out a client resolve an issue due to a change in behavior from CF9 to CF10. CF10 automatically adds the secure flag to cookies when the request is over a secure HTTPS channel. CF9 and lower do not add the secure flag to your JSESSIONID cookies when the request is over HTTPS, you can set a flag to force it in all cases (by editing jrun-web.xml), but there is no way to do it conditionally.

It turns out this is a feature of Tomcat, not CF10

I did some digging in the Tomcat source code and found that this functionaility is hard coded into Tomcat, and there is no config to control it. If you are curious you can see the source code here: ApplicationSessionCookieConfig:141

// Always set secure if the request is secure
if (scc.isSecure() || secure) {
    cookie.setSecure(true);
}

This can lead to session loss, BUT it is also a good security feature

The secure flag on a cookie means that it will only send the cookie over a secure channel like HTTPS, so when a JSESSIONID cookie is set with a secure flag, it will not be sent on a HTTP request that is not HTTPS, so you have two sessions one for HTTPS and one for HTTP.

You can't securely share a session on both HTTP and HTTPS

While a lot of people want to share a session between http and https there is no way to do it in a secure way, once the JSESSIONID is sent over HTTP you have an opportunity for a man in the middle to snatch it.

A good way to solve this problem is to only use sessions on HTTPS, for any url that requires a session make sure it is over HTTPS. The best is to simply use HTTPS for everything.

For this particular customer it would take a major rewrite to accomodate all HTTPS or to switch away from J2EE sessions (note for CFID/CFTOKEN sessions you can controll the secure flag of the cookies in the Application.cfc using this.sessionconfig.secure=true/false). So they needed a workaround.

Here is a workaround (but know that it lessens the security of your sessions over https)

Keep in mind this workaround decreases security. So we need to remove the secure flag from the JSESSIONID cookie, and there is no easy way to do this in Tomcat or CFML that I'm aware of. So my solution was to rewrite the cookie in IIS using URL Rewrite, here's how you do this:

  1. Install Microsoft URL Rewrite for IIS: http://www.iis.net/downloads/microsoft/url-rewrite
  2. Close IIS, and open it again.
  3. Click On the root server level node of IIS (so that this is applicable to all sites on your server),
  4. Double Click on the URL Rewrite icon
  5. Click on Add Rule(s)
  6. Under Outbound Rules select Blank Rule
  7. Give it an arbitrary name, eg RemoveSecureFlagOnJSESSIONID
  8. Under Match, select Matching Scope: Server Variable
  9. For Variable name use: RESPONSE_Set-Cookie
  10. Variable Value: Matches Pattern
  11. Using: Regular Expressions
  12. Pattern: ^(.*JSESSIONID.*)Secure;(.*)$
  13. Under Action, Action Type: Rewrite
  14. Action Properties: Value: {R:1}{R:2}
  15. Check replace existing server variable

Or here's how you can add it to a single site using web.config files:

<rewrite>
            <outboundRules>
                <rule name="RemoveSecureJessionID">
                    <match serverVariable="RESPONSE_Set-Cookie" pattern="^(.*JSESSIONID.*)Secure;(.*)$" />
                    <action type="Rewrite" value="{R:1}{R:2}" />
                </rule>
            </outboundRules>
</rewrite>

Note you can also use this technique to improve the security of JSESSIONID cookies on CF9 and lower by adding a HttpOnly flag or a secure flag to the cookie.



Related Entries

This entry was:

Comments

Hi Pete,

Why will Tomcat give the following configuration when it will not honor it?
<cookie-config>
<secure>true/false</secure>
Hi Shilpi, Good question -- it appears that setting secure=false has no effect, but setting secure=true does have an effect. Would be a good question to ask if you guys have some friends on the Tomcat core team.

It is a good security feature, but I was surprised that there is no config option to turn it off.
hmmmmm i would be interested in knowing the reasoning behind it. Let's see what i get.

Thanks for sharing the workaround.
Can you expand on this Pete in terms of your "ColdFusion 10 Lockdown Guide" Session Cookie Settings recommendations? Is it relevant?
Really great work there, Pete, both the understanding of the problem, and the available solutions (and workaround). Thanks for sharing it.

I would ask for just a couple of clarifications, if you don't mind.

First, you say in the opening paragraph that "CF10 automatically adds the secure flag to cookies when the request is over a secure HTTPS channel". Is that limited only to the session cookies (jsessionid or cfid/cftoken), or is that all cookies set from within CF? That might be interesting for some to know (if it is all cookies set in CF).

Similarly, you say "CF9 and lower do not add the secure flag to your JSESSIONID cookies when the request is over HTTPS, you can set a flag to force it in all cases, but there is no way to do it conditionally." Again, is that referring only to the session cookies( jsessionid and cfid/cftoken)? Or perhaps only to jsessionid (as you state)? or is it all cookies set from CF?

I see that you have the rule changing only the jsessionid cookie, and I do realize that the crux of the problem here is that with the impact on session cookies, that's causing the loss/confusion of sessions. So any other cookies would remain as created (with respect to the secure flag), given that rule, right? Is that because you feel it's best not to tamper with other cookies, and that for most users, there would not be confusion if the rest of their cookies (sent from CF) remained unchanged with respect to this?

Also, one might wonder whether the this.sessionconfig.secure=true/false (or the Admin setting) apply only to the older cfid/cftoken cookies and to JEE session cookies (jsessionid). It's not clear from here. Do you know?

(And Pete, would you agree that that app.cfc setting you showed is just the app-specific implementation of the new CF 10 Admin feature, on the "Memory Variables" page, in the section "Session Cookie Settings", as the "Secure Cookie" setting? That might be worth mentioning when you discuss that application.cfc setting, or you can leave this as the way some can connect that dot, if indeed they should. I bow to your expertise in this area.)

Finally, Shilpi, are those two settings (in app.cfc or the admin) SUPPOSED to be changing the processing of the session cookie, regardless of whether we are using JEE sessions or not? Someone reading this could think it applies only to cfid/cftoken. I'd hope, though, that it should apply to either kind of sessions.

I do realize that even if you intended that it should, it could not on Tomcat until there's a change in that hard-coded limitation that Pete's found.

Thanks to both of you for your participation in the discussion of this matter.
@Richard - If anything this finding is pro for using J2EE sessions from a security perspective, but you can also accomplish the same using CFID/CFTOKEN by conditionally setting the this.sessionconfig.secure=cgi.https IS "on" in your Application.cfc in CF10.
@Charlie, great questions - I'll try to answer them all here and also update the blog entry:

First this finding is only specific to the J2EE session cookie (I would call it jsessionid, but you can rename it in the config if you wanted to). It does not automatically add the secure flag to other cookies set with cfcookie, or otherwise, and it does not apply to CFID CFTOKEN session cookies.

When I was talking about setting session cookies on CF9/JRun - I was referring to j2ee / jsessionid cookie, you can make all jsessionid's have a secure flag by editing the jrun-web.xml file, see http://www.petefreitag.com/item/740.cfm but there is no way to do it conditionally.

I need to test and see if jsessionid can be controlled via this.sessionconfig in Application.cfc, I do know that the this.sessionconfig.secure does not matter on jsessionid, but I'm not sure about the other settings.

Hope that helps clarify some of this.
Thanks for that Pete. I agree with your preference for J2EE sessions.

Thanks also to Charlie for adding questions I couldn't conceive of but wish I had! :-)

@Pete, as a result, could I précis your findings in terms of ColdFusion 10 and J2EE sessions as...

Due to a hardcoded implementation in Tomcat, requests made over HTTPS will always set secure=true in the JSESSIONID cookie. If the "Secure Cookie" setting in the ColdFusion Administrator "Server Settings > Memory Variables > Session Cookie Settings" is not checked (false) or this.sessioncookie.secure is set to false in Application.cfc, requests made over HTTP will always set secure=false in the JSESSIONID cookie. Therefore sites where requests flick between HTTP and HTTPS will create two JSESSIONID cookies, where one has secure=true and the other has secure=false. This will result in two disconnected sessions being created with the associated implications for session scope.

That said, as I write this, would it be right to say that the "Secure Cookie" setting has no effect if the JSESSIONID is set by an HTTPS request. It will always be secure=true because Tomcat trumps your preference? Your preference will only be respected when a HTTP request is made? Would that mean that if "Secure Cookie"=true you could still keep the same session if your requests from a site flicked between HTTPS and HTTP as Tomcat would enforce secure=true for the HTTPS request and the CFAdmin setting would enforce secure=true for the HTTP request?

Or am I missing something?
@Richard - I did some quick testing and it appears that the CF admin settings, and the Application.cfc this.sessionconfig settings do not apply to JSESSIONID, they are only for CFID CFTOKEN sessions.
Thanks, Pete, for your response to my questions (and Richard, for your kind regards to them).

@Pete, as for your last comment, was that regarding CF10? If so, I would wonder if that might be only because of the Tomcat issue you've identified.

Still looking forward to Shilpi or someone at Adobe addressing the questions like that which I'd also raised yesterday.
@Charlie - Yes my last comment was in reference to CF10 because the settings this.sessionconfig (and corresponding CF admin settings) were introduced in CF10.
The settings added in CF10 are for ColdFusion session cookies ( CFID/CFTOKEN/CFAUTHORIZATION). JSESSIONID settings are configured at server level in web.xml.
Your interesting URLrewrite discovery may inform a solution to a problem that is vexing me right now: apparently, the SetDomainCookies setting does not apply to jsessionid, therefore not allowing cross-subdomain J2EE sessions. When an *additional* jsessionid cookie is written (without subdomain) it doesn't help, because the subdomain-specific cookie rules. Do you think URLrewrite could be used to write the jsessionid cookie *uniquely* to be a domain cookie without subdomain?

Post a Comment




  



Spell Checker by Foundeo

Recent Entries



foundeo


did you hack my cf?