Monday, December 22, 2008

Fixing Both Missing HTTPOnly and Secure Cookie Flags

Submitted by Ryan Barnett 12/22/2008

In a previous post I showed how you can use both ModSecurity and Apache together to identify/modify SessionIDs that are missing the HTTPOnly flag. I received some feedback where people were asking how to accomplish the same thing but for the "Secure" cookie flag which instructs the browser to *only* send the SessionID back over an SSL connection.
If you are only interested in addressing the missing "Secure" cookie flag, then you can simply take the example from the previous post and edit it slightly to swap out "httponly" with "secure". If, however, you want to try and address both of these issues together, then you will need to change the rule set approach a bit so that it works correctly. This is because there are now three different scenarios you have to account for -
  • Missing HTTPOnly flag
  • Missing Secure flag (if the SessionID is being sent over an SSL connection)
  • Missing both HTTPOnly and Secure flags

With this in mind, here is an updated rule set that will handle both missing HTTPOnly and Secure cooking flags.

#
# First we want to capture Set-Cookie SessionID data for later
inspection
SecRule RESPONSE_HEADERS:/Set-Cookie2?/
"(?i:(j?sessionid(php)?sessid(aspjservjw)?session[-_]?(id)?cf(idtoken)sid))"
"phase:3,t:none,pass,nolog,setvar:tx.sessionid=%{matched_var}"

#
# We now check the saved SessionID data for the HTTPOnly flag and set an Apache
# ENV variable if it is missing.
SecRule TX:SESSIONID "!(?i:\;?
?httponly;?)"
"phase:3,t:none,setenv:httponly_cookie=%{matched_var},pass,log,auditlog,msg:'AppDefect:
Missing HttpOnly Cookie Flag.'"

#
# Next we check the saved SessionID data for the Secure flag (if this is an SSL session)
# and set an Apache ENV variable if it is missing.
SecRule SERVER_PORT "@streq 443"
"chain,phase:3,t:none,pass,log,auditlog,msg:'AppDefect: Missing Secure Cookie
Flag.'"
SecRule TX:SESSIONID "!(?i:\;? ?secure;?)"
"t:none,setenv:secure_cookie=%{matched_var}"

#
# The final check is to see if BOTH of the HTTPOnly and Secure cookie flags are missing
# and set an Apache ENV variable if they are missing.
SecRule TX:SESSIONID
"!(?i:\;? ?httponly;?)" "chain,phase:3,t:none,pass,log,auditlog,msg:'AppDefect:
Missing HttpOnly and Secure Cookie Flag.'"
SecRule SERVER_PORT "@streq
443" "chain,t:none"
SecRule TX:SESSIONID "!(?i:\;? ?secure;?)"
"t:none,setenv:secure_httponly_cookie=%{matched_var}"

#
# This last section executes the Apache Header command to
# add the appropriate Cookie flags
Header set Set-Cookie "%{httponly_cookie}e; HTTPOnly"
env=httponly_cookie
Header set Set-Cookie "%{secure_cookie}e; Secure"
env=secure_cookie
Header set Set-Cookie "%{secure_httponly_cookie}e; Secure;
HTTPOnly" env=secure_httponly_cookie

These rules will both alert and fix these cookie issues. You may want to switch the actions to "nolog" so that you are not flooded with alerts.

Friday, December 19, 2008

Helping Protect Cookies with HTTPOnly Flag

Submitted by Ryan Barnett 12/19/2008

If you are unfamiliar with what the HTTPOnly cookie flag is or why your web apps should use it, please refer to the following resources -

The bottom line is this - while this cookie option flag does absolutely nothing to prevent XSS attacks, it does significanly help to prevent the #1 XSS attack goal which is stealing SessionIDs. While HTTPOnly is not a "silver bullet" by any means, the potential ROI of implement it is quite large. Notice I said "potential" as in order to provide the intended protections, two key players have to work together -

  • Web Applications - whose job it is to append the "HTTPOnly" flag onto all Set-Cookie response headers for SessionIDs, and
  • Web Browsers - whose job it is to identify and enforce the security restrictions on the cookie data so that javascript can not access the contents.

The current challenges to realizing the security benefit of the HTTPOnly flag is that universal adoption in both web apps and browsers is still not there yet. For example, depending on your web app platform, you may not have an easy mechanism to implementing this feature. For example - in Java you could following the example provided here on the OWASP site - http://www.owasp.org/index.php/HTTPOnly#Using_Java_to_Set_HTTPOnly, however this doesn't work well for the JSESSIONID as it is added by the framework. Jim Manico has been fighting the good fight to try and get Apache Tomcat developers to implement his patch to add in HTTPOnly support - http://manicode.blogspot.com/2008/08/httponly-in-tomcat-almost.html. The point is that with so many different web app development platforms, it isn't going to be easy to find support for this within every web app that you have to secure...

As for browsers - they too have sporadic, non-consistent adoption of HTTPOnly. It was for this reason that the OWASP Intrinsic Security group has started an RFC Spec for HTTPOnly - http://groups.google.com/group/ietf-httponly-wg. Hopefully this group will get some traction with the various browser developers.

So, at this point you might be asking yourself - Ryan, that is interesting news and all, but what can a web application firewall do to help with this issue? I would then in turn reply - Great question, I am glad that you asked. ;)

One of my pet peevs with the web application security space is the stigma that is associated with a WAF. Most everyone only focuses in on the negative security and blocking of attacks aspects of the typical WAF deployment and they fail to realize that WAFs are a highly specialized tool for HTTP. Depending on your circumstances, you may not ever intend to do blocking. There are many other use-cases for WAFs and how they can help, in this case as a tactical response tool to help address an underlying vulnerability In this case, we could monitor when back-end/protected web applications are handing out SessionIDs that are missing the HTTPOnly flag. This could raise an alert that would notify the proper personnel that they should see if editing the web language code is possible to add this feature in. A rule to do this with ModSecurity would look like this -

# Identifies SessiondIDs without HTTPOnly flag
#
SecRule RESPONSE_HEADERS:/Set-Cookie2?/ "!(?i:\;? ?httponly;?)" "chain,phase:3,t:none,pass,log,auditlog,msg:'AppDefect: Missing HttpOnly Cookie Flag.'"
SecRule MATCHED_VAR "(?i:(j?sessionid(php)?sessid(aspjservjw)?session[-_]?(id)?cf(idtoken)sid))" "t:none"

While this rule is pretty useful for identifying and alerting of the issue, many organizations would like to take the next step and try and fix the issue. If the web application does not have a way to add in the HTTPOnly cookie flag option internally, you can actually leverage ModSecurity+Apache for this purpose. ModSecurity has the ability to set environmental data that Apache reads/acts upon. In this case, we can modify our previous rule slightly to use the "setenv" action and then we add an additional Apache "header" directive that will actually overwrite the data with new Set-Cookie data that includes the HTTPOnly flag -

# Identifies SessiondIDs without HTTPOnly flag and sets the "http_cookie" ENV
# Token for Apache to read
SecRule RESPONSE_HEADERS:/Set-Cookie2?/ "!(?i:\;? ?httponly;?)" "chain,phase:3,t:none,pass,nolog"
SecRule MATCHED_VAR "(?i:(j?sessionid(php)?sessid(aspjservjw)?session[-_]?(id)?cf(idtoken)sid))" "t:none,setenv:http_cookie=%{matched_var}"

# Now we use the Apache Header directive to set the new data
Header set Set-Cookie "%{http_cookie}e; HTTPOnly" env=http_cookie

The end result of this ruleset is that ModSecurity+Apache can transparently add on the HTTPOnly cookie flag on the fly to any Set-Cookie data that you define. Thanks goes to Brian Rectanus from Breach for working with me to get the Header directive syntax correct.

Hopefully the data presented here will help people who would like to have the security benefit of this flag however are running into challenges with implementing it within the app.