site logoTune The Web

Secure cookies

Introduction

Cookies are used by nearly all websites for various reasons, to manage state, handle logins or simply to track you for advertising purposes. It's therefore usually very important that they are kept safe. The way they work is that a server asks your browser to set a cookie, by giving a name, value (amongst other things), which the browser then stores (either in disk or memory depending on the cookie type). Each subsequent request to the website sends the cookies along with the request.

Unfortunately there are two major issues with cookies:

  1. They are not protocol specific: a cookie set on the HTTPS website (which is secure) will also be available to the HTTP version (which is not secure).
  2. They can be read by javascript on the browser: so if a hacker manages to run some javascript on your website (using XSS) then your cookies can be read.

There are two optional settings each cookie can have set which largely address these issues: HttpOnly means that the cookies should not be accessible from client side scripts and Secure means that the cookie should only be sent across HTTPS requests.

Note: there is also a third issue whereby cookies can leak, or be set, across subdomains, but that's more complicated, and still largely be mitigated in the same way, though the HSTS setting with includeSubdomain will further secure this (though with some downsides).

How to set it up

Whichever application creates the cookies, really should create them correctly. This is normally a back-end application server (e.g. Tomcat, Jboss, PHP, NodeJs or whatever) rather than the web server (e.g. Apache, Nginx, IIS). How your back end application server sets these will depend on the software it uses and as beyond the scope of this site, which attempts to explain general theories.

However it is possible to get your web server to force these settings, which can be a very useful fail safe. For example in Apache this would done with the following config to alter any Set-Cookie headers returned through Apache:

# Rewrite any session cookies to make them more secure # Make ALL cookies created by this server are HttpOnly and Secure Header always edit Set-Cookie (.*) "$1;HttpOnly;Secure"

This means these flags are set even if the programmer forgets to set these settings when creating the cookies in the applications servers.

If a particularly cookie is needed to be used by client-side scripting, then you can exclude certain cookies with config like this:

# Rewrite any session cookies to make them more secure # Make ALL cookies created by this server are HttpOnly and Secure # (except the SPECIAL-CLIENT cookie which can't be HttpOnly and is already set to Secure) Header edit Set-Cookie ^((?!SPECIAL-CLIENT).*)$ $1;HttpOnly;Secure

And you can have exceptions for multiple cookies:

# Rewrite any session cookies to make them more secure # Make ALL cookies created by this server are HttpOnly and Secure # (except the SPECIAL-CLIENT cookie and OTHER-COOKIE which can't be HttpOnly and is already set to Secure) Header edit Set-Cookie ^((?!(SPECIAL-CLIENT|OTHER-COOKIE).*)$ $1;HttpOnly;Secure

Finally it is possible that above settings will lead to one of more of these flags being set twice (once by the back end system, and once by Apache). While this doesn't seem to cause any browsers any issues, it's not really correct and so should only be set once. This can be corrected with a little extra trickery:

#Strip off double Secure or HttpOnly settings as if App and Apache sets above you can sometimes get both Header edit Set-Cookie ^(.*);\s?Secure;?\s?(.*);\s?Secure;?\s?(.*)$ "$1; $2; $3; Secure" Header edit Set-Cookie ^(.*);\s?HttpOnly;?\s?(.*);\s?HttpOnly;?\s?(.*)$ "$1; $2; $3; HttpOnly" #Strip off double ;; settings Header edit Set-Cookie ^(.*);\s?;\s?(.*)$ "$1; $2"

Support

Support for both HttpOnly and Secure flags on cookies is very strong with all modern web browsers supporting them.

On the web server side, all applications servers that set cookies should allow this. Apache makes this very easy to enforce at a web server level, as per above, IIS seems to have the facility to do the same, but not sure how to do this with Nginx (please comment below if you know how!).

The downsides

The only real downside to this is if you need a cookie, either for HTTP requests, or for client side scripting then you shouldn't set these flags or this will break. Though these can often be excluded as the example above shows.

It could also be argued this that these settings mask where the real issue should be resolved (by the application setting the cookie correctly), and while I agree with that I don't think that's a good enough reason not to add this extra protection at the web server level.

Summary

The are only very limited reasons why cookies should not be both Secure and HttpOnly, so it's strongly recommended that above settings are used. And that the defaults are put in at a web server level, to protect against this not being set.

This page was originally created on and last edited on .

How useful was this page?