I've made specific suggestions to the Apache Tomcat core developer team to add HTTPOnly support to Tomcat 5.5 (for starters). The adoption is slow-going since it involves changes to three of the most core files of Tomcat.
Here is how you can get HTTPOnly support
NOW while you wait for official adoption.
1) First download the Tomcat source code and be able to build the core server via ANT. See
http://tomcat.apache.org/tomcat-5.5-doc/building.html for instructions. Although the link above points to Tomcat 5.5, the changes I'm suggesting below will work for
any Tomcat build.
Once you have downloaded the Tomcat code and have set up your build environment, you will need to make the following changes to at least org.apache.catalina.connector.Request.java and org.apache.catalina.connector.Response.java. You could (should) also make changes to org.apache.tomcat.util.http.ServerCookie.java if you require a very scalable solution where every StringBuffer.append matters; but that addition is beyond the scope of this post.
2) org.apache.catalina.connector.Request.doGetSession(boolean create) is where the session cookie (JSESSIONID) is initially created. You are going to need to change this. This first change is at approximately loc 2321 of the file org.apache.catalina.connector.Request.java (for Tomcat 5.5).
//this is what needs to be changed
//response.addCookieInternal(cookie);
//this is whats new
response.addCookieInternal(cookie, true); }3) In order to support the new HTTPOnly version of Response.addCookieInternal, we need to modify the functionality of org.apache.catalina.connectorResponse.addCookieInternal. The following are my suggested backward-compatible changes:
public void addCookieInternal(final Cookie cookie) {
addCookieInternal(cookie, false);
}
public void addCookieInternal(final Cookie cookie, boolean HTTPOnly) {
if (isCommitted())
return;
final StringBuffer sb = new StringBuffer();
//web application code can receive a IllegalArgumentException
//from the appendCookieValue invokation
if (SecurityUtil.isPackageProtectionEnabled()) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run(){
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(),
cookie.getValue(), cookie.getPath(),
cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
return null;
}
});
} else {
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(), cookie.getValue(),
cookie.getPath(), cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
}
//of course, we really need to modify ServerCookie
//but this is the general idea
if (HTTPOnly) {
sb.append("; HttpOnly");
}
//if we reached here, no exception, cookie is valid
// the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
// RFC2965 is not supported by browsers and the Servlet spec
// asks for 2109.
addHeader("Set-Cookie", sb.toString());
cookies.add(cookie);
}
Any feedback is appreciated.
PS: For more on HTTPOnly and how it can be a part of your defense-in-depth web application security strategy, see
http://msdn2.microsoft.com/en-us/library/ms533046.aspx