Don't Share Your Cookies: Drupal and the HttpOnly Flag

Tom's picture
Tags: 

a cookieJeff Atwood has an interesting discussion of the HttpOnly flag and how it can help protect your site from cross-site scripting attacks. For those hoping for a quicker rundown than Jeff's excellent explanation: XSS attacks are based upon the injection of third-party Javascript into your site. This usually happens via a comment or search form — really, it can be anything that accepts user input that is then rendered as part of the site's HTML. If that user input isn't properly sanitized it can trick other users' browsers into running the attacker's Javascript as if it were part of your site.

Once that happens the attacker has access to all sorts of goodies. The most valuable is the document.cookie object, which will generally contain the string that identifies your session to the site. They'll shuttle its contents off to their own server, and with your session in hand they can pretend to be you (at least until the session expires), doing whatever sorts of authenticated tasks you have access to on the site.

The HttpOnly flag tells most modern browsers that scripts shouldn't be allowed access to the cookie — it's for the webserver's eyes only. Handy! So what would it take to get this into Drupal?

Well, with the caveat that I haven't previously dug into Drupal's session-handling code, it looks like a relatively simple fix. In both d5 and d6 there's a function called sess_regenerate that's called at login and which sets the session cookie. This seems to be the only call to setcookie() in core, in fact, making me think that it's the whole enchilada as far as HttpOnly support goes. The line in question looks like this:

setcookie(session_name(), '', time() - 42000, '/');

Support for the HttpOnly flag in the PHP setcookie() function only arrived in PHP 5.2, but as this post illustrates it's pretty easy to get around that by simply setting the cookie with a direct call to header().

So why am I noting this instead of providing a patch? Unfortunately, as Jeff notes, the XMLHttpRequest object undercuts the utility of HttpOnly; an attacker has only to make an AJAX request to the server, then they can get at your cookies anyway, regardless of the flag. I imagine the browsers will fix this eventually, but for now it would be such a trivial workaround for an attacker that there isn't much point in adding HttpOnly support.

So it remains the case that to defend against XSS in Drupal you must be vigilant about sanitizing user input. Fortunately the APIs that have developed within Drupal make this relatively easy — most of the time it's not something you'll have to think about at all. But remember: check_plain() is your friend (and $_GET and $_POST are your enemies)!

Photo by Flickr user Crysti, used under a Creative Commons license.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockcode>
  • Lines and paragraphs break automatically.
  • You may post block code using <blockcode [type="language"]>...</blockcode> tags. You may also post inline code using <code [type="language"]>...</code> tags.

More information about formatting options

Captcha
Are you a robot? We usually like robots, but not in our comments.