Setting up HTTPOnly Session Cookies for ColdFusion
By Pete Freitag
Internet Explorer pioneered a great security feature for cookies called HTTPOnly, when this flag is set the browser does not allow JavaScript to access the cookie. Now that all modern browsers support this flag it can reduce the risk of session hijacking due to cross site scripting. For that reason many security auditors will take marks off if you are not using it for your session identifier cookies (eg cfid
, cftoken
, and jsessionid
).
I recently updated my ColdFusion Security Scanner, hackmycf.com to check for the omission of HTTPOnly session cookies. It now provides a warning if the cfid
, cftoken
, or jsessionid
cookies do not set the HTTPOnly flag. We now also offer a subscription service which will scan your server automatically on a daily, weekly, monthly or quarterly basis.
ColdFusion 9 also introduced an attribute on the cfcookie
tag called httponly
which you can set to a boolean value. Prior to CF9 you can still create HTTPOnly cookies with ColdFusion but you have to use cfheader
instead of cfcookie
to write the cookies.
If running ColdFusion 10 or Above
ColdFusion 10 added a HTTPOnly setting to ColdFusion administrator under Server Settings » Memory Variables you can simply check the checkbox and you should be good.
You can also force this in your Application.cfc
by specifying:
this.sessioncookie.httponly = true;
If running ColdFusion 9.0.1
ColdFusion 9.0.1 update added support by a java system property called coldfusion.sessioncookie.httponly
you can turn this on by editing the jvm.config and adding the following to the java.args
:
-Dcoldfusion.sessioncookie.httponly=true
If you are running Standalone (not multi-server/j2ee mode) you can add this in the ColdFusion Administrator
If Running CF 9.0 or greater
If you have not upgraded to 9.0.1 yet, or would rather solve this issue in your code, here?s an example Application.cfc file you could use:
<cfcomponent> <cfset this.sessionmanagement = true> <cfset this.setclientcookies = false> <cffunction name="onSessionStart"> <cfcookie name="CFID" value="#session.cfid#" httponly="true"> <cfcookie name="CFTOKEN" value="#session.cftoken#" httponly="true"> </cffunction> <cfcomponent>
If Running CF 8 or Lower and using Application.cfc
<cfcomponent> <cfset this.sessionmanagement = true> <cfset this.setclientcookies = false> <cffunction name="onSessionStart"> <cfheader name="Set-Cookie" value="CFID=#session.CFID#;path=/;HTTPOnly"> <cfheader name="Set-Cookie" value="CFTOKEN=#session.CFTOKEN#;path=/;HTTPOnly"> </cffunction> <cfcomponent>
Make sure you have setclientcookies = false
specified.
If Using Application.cfm
If you are still using an Application.cfm
file, you can use the following:
<cfapplication setclientcookies="false" sessionmanagement="true" name="test"> <cfif NOT IsDefined("cookie.cfid") OR NOT IsDefined("cookie.cftoken") OR cookie.cftoken IS NOT session.CFToken> <cfheader name="Set-Cookie" value="CFID=#session.CFID#;path=/;HTTPOnly"> <cfheader name="Set-Cookie" value="CFTOKEN=#session.CFTOKEN#;path=/;HTTPOnly"> </cfif>
If using J2EE Session Cookies (jsessionid)
If you are using CF9.0.1 or greater use the java system property described above.
If you are using CF9.0 or lower, then you can edit the jrun-web.xml file located in WEB-INF as described here to enabled HTTPOnly cookies.
Jason Dean has also come up with a way to do this in onSessionStart as well.
Setting The Secure Flag
If your site runs over HTTPS, you should also be setting the secure
flag on your cookies. When the browser is given a cookie with the secure flag it only sends the cookie over a HTTPS connection. Add the following to your Application.cfc and update the ColdFusion Administrator settings:
this.sessioncookie.secure = true;
The above will take care of the CFID
and CFTOKEN
cookies, if you also have a JSESSIONID
cookie then you need make sure this cookie has the secure flag too. In most cases this is taken care of automatically by the J2EE server (eg Tomcat), but if not then you may need to do something like this on the Web Server to add the Secure
flag to the cookie.
Setting up HTTPOnly Session Cookies for ColdFusion was first published on September 13, 2010.
If you like reading about httponly, cookies, session, cfid, cftoken, jsessionid, or security then you might also like:
- J2EE Sessions in CF10 Uses Secure Cookies
- Client Variable Cookie CFGLOBALS Includes Session Ids
- Firefox Now Supports HttpOnly Cookies
- SameSite Cookies with IIS
The FuseGuard Web Application Firewall for ColdFusion & CFML is a high performance, customizable engine that blocks various attacks against your ColdFusion applications.
CFBreak
The weekly newsletter for the CFML Community
Comments
I have been relying on ajax passing on the CFID and token from the main session through async requests.
-Brian
-Brian
http://www.jeffryhouser.com/index.cfm/2010/11/10/Setting-HTTPOnly-and-Secure-for-the-ColdFusion-Session-cookies
And from this I derived this which seems to work well. Tell me if you see any issues with this and leaving 'setclientcookies=true'.
<cfset this.clientmanagement = true />
<cfset this.setclientcookies = true />
<cffunction name="onSessionStart" access="public" returntype="void" output="false">
<cfset var LOCAL = {} />
<cfset LOCAL.cookie = ";domain=" & cgi.http_host & ";path=/;HTTPOnly;" />
<cfif StructKeyExists(cgi, "https") and cgi.https is "on">
<cfset LOCAL.cookie &= "Secure;" />
</cfif>
<cfset LOCAL.cfidCookie = "cfid=" & session.cfid & LOCAL.cookie />
<cfset LOCAL.cftokenCookie = "cftoken=" & session.cftoken & LOCAL.cookie />
<cfcookie name="cfid" expires="now" />
<cfcookie name="cftoken" expires="now" />
<cfheader name="Set-Cookie" value="#LOCAL.cfidCookie#">
<cfheader name="Set-Cookie" value="#LOCAL.cftokenCookie#">
</cffunction>
That may only be required if using Application.cfm
http://blog.fusedevelopments.com/2011/03/coldfusion-9-hotfix-1-causes-session.html
I believe your suggestion for CF 9.0.1 is incorrect.
Your sussestion is that using -Dcoldfusion.sessioncookie.httponly=true will simply make jsessionid httponly.
However, what I believe it is doing is setting any session only cookies to httponly.
The main issue is the definition of seesioncookie. Instead of being "cookies that define the users session", I believe the real definition is "cookies that are set to expire at the end of the browser session"
So if you currently have code like "<cfset Cookie.ShowTab = 0>", and then have javascript that works with that cookie, then your code will break because the ShowTab cookie is httponly and not available to javascript.
Your described behaviour appears correct because jsessionid is a end-of-session cookie.
I beleive you shouldn't use coldfusion.sessioncookie.httponly unless you have reviewed the code for all sites on the server.
Possible workarounds are to always set a date expiry, or set the cookie in JS only and make the CF code allow for the cookie to not exist yet.
I haven't tested with cfcookie, but expect the same behaviour.
Hopefully CF10 will have httponly and secure settings for the jsessionid cookie as part of Application.cfc/cfapplication.
At the end of this post you mention setting the "secure" flag on your cookies. Is that eluding to it being possible to set that as a JVM config argument as well or is this only available in the jrun-web.xml?
@Ted - Glad you found it useful.
I'm not prepared to uninstall the patches to retest, but anyone reading this should disregard my previous comments if they are fully patched up.