On HttpOnly, Firefox-specific XSS and this years major Livejournal XSS attack
2018 Update: This is an old article that contains security advice that might no longer be correct. It’s here for historical reasons, but should no longer be used as a reference for security matters.
Yep, thats a long title, but they are all related to each other in some way. In the first few paragraphs I will explain what cookies are and XSS. You might want to skip ahead if you already know what this is.
Sessions, Cookies
HTTP is stateless. This means that every request to the server is a ‘new’ one and normally there is no relation to a first or second request. To allow maintaining a session or ‘state’ between multiple requests, HTTP cookies are used.
A cookie is basically a HTTP header with a tiny piece of information that gets re-sent with every request to the server. A popular way to make use of this is through PHP’s $_SESSION system. This sends a cookie with a unique id to the client that allows PHP to retain a users’ information across pages.
XSS
If you allow users to for example comment on one of your pages and allow
(certain) html, it is sometimes possible to inject a piece of javascript.
There are many tricks to evade the so-called html sanitizers..
strip_tags() is PHP’s built-in sanitizer, but it doesn’t work really
well.. if, for example, you would allow users to use a <p>
tag, which
might seem harmless, there would be tricks to abuse the style=""
or
onclick=""
attributes, just to name a few.
XSS and cookies
So how do you abuse javascript and cookies combined?
Because with for example PHP’s session system, you can use the contents of
the cookie to steal someone’s session. The hacker would be logged in as you
and might able to change your password and log you out afterwards. The
contents of the cookies is stored in the javascript variable document.cookie
.
HttpOnly, a solution
Microsoft came up with a way to prevent this from happening, ever since Internet Explorer 6.0 (starting from Windows XP SP1). They added an extra piece of information to a cookie, that will still allow the use of cookies in the way you are used to, but it will prevent the cookie from being read by javascript (basically it is invisible for javascript). Be sure to check out microsofts spec at MSDN.
Safari and Opera quickly started supporting this. Because of this it is becoming pretty useful to use in practice. Remember that this doesn’t mean you can just accept any html on your site, you should still always sanitize the bad stuff or not allow it at all! But in the case you missed something, it can make it a lot more difficult for your attacker to steal sessions.
UPDATE: Safari/Opera actually ignore it, my excuses, I didn’t check my sources.
Under the hood
Normally, a cookie header will look like this:
Set-Cookie: USER=username; expires=Wednesday, 09-Nov-99 23:12:40 GMT
But with the HttpOnly, it will look like this:
Set-Cookie: USER=username; expires=Wednesday, 09-Nov-99 23:12:40 GMT; HttpOnly
It’s a small change, and all normal browsers should still accept this even if they don’t understand the HttpOnly part. There is an exception though, and it goes by the name of IE 5 for mac. This browser won’t understand the cookie and totally ignores it. Personally I don’t support this browser for any application anymore, as there are too many bugs in this browser. But if your boss wants it, this might prevent you from using HttpOnly.
PHP support
A guy named Scott MacVicar created a patch for PHP that will add an extra
parameter to set_cookie() to enable HttpOnly
for your cookies. The
patch should also enable this by default for the session system.
If the patch will get accepted we will likely be able to use this in PHP 6.0 and perhaps even PHP 5.2, I’m looking forward to that. There is a chance though, because of the IE5/mac breakage that it eventually won’t be auto-enabled for the session system.
So what about firefox?
Firefox doesn’t support it, there is currently a bug open for it
(Bug #178993). There was an initial solution posted over 2 years ago
(January 2004). And a few other patches later on, but the mozilla folks
refused all of them because they want to maintain the exact format of
cookies.txt
(the file they use to store cookies), because other
applications might rely on that format. A few solutions for that have been
posted, but it doesn’t seem like a high priority for them.
A workaround for firefox (kind of)
There have been solutions for firefox that also blocked reading of cookies by
javascript. Firefox has a magic function __defineGetter__
that can block
reading of variables. To do this for all cookies on your site, include the
following snippet on top of your html page:<
HTMLDocument.prototype.__defineGetter__("cookie",function (){return null;});
However, you can’t rely on this! There are still ways to get this cookie if
ehe hacker can somehow create an iframe in your html page. The hacker has a
reference to the same cookies if he uses the data:
protocol in the
src=""
attribute. This will still make it a bit harder to steal cookies, so
it’s not a bad idea to implement. For a longer explanation of this workaround,
check out http://www.wisec.it/sectou.php?lang=en.</p>
The LiveJournal case
The same people who submitted the initial firefox-patch (see above) 2 years ago, also got hit by the attack in January 2006. Over 46% accounts were hijacked. This were over 900.000 stolen accounts. (check out their post about their solution.)
The reason they got hit by this is because they allowed users to use remote
CSS stylesheets for their pages. CSS used to be only a specification for how
html elements would look like on a page, but since a few years it has become
more dynamic and now there are ways to exploit CSS with XSS attacks through
for example IE’s non-standard behavior:
attribute and Firefox’
-moz-binding:
attribute (there are more you can exploit, but its outside the
scope of the article). These attributes allow an author to create a custom
behavior for a HTML element. The technique to do this for Firefox is called
XBL.
Normally, when a page is loaded from domain A, and another (in a different
frame for example) is loaded from domain B. Malicious scripts from domain B
can never access cookies from domain A. This is called a same origin check
.
This generally works in all browsers for all kinds of content, but an
exception is XBL. (see bug #324253.)
Apparently this requires some major changes in how firefox works. The last
comment in this bug is from February this year (2006). I hope they will wake
up some day soon and make our life a little bit easier by both supporting
HttpOnly
and securing XBL.
So the LiveJournal attack could happen because the hackers used XBL in their
CSS, which in turn accessed the HTTP cookies through javascript. The attack
didn’t affect users of other browsers, because: A) they support HttpOnly
,
B) even if they wouldn’t.. the microsoft equivalent of XBL, which is .HTC
files, don’t work across different domains.
Comments
Anonymous •
lame ;)Krys •
rock on. you are my hero.. when my lj gets hacked will you save me?valerie •
sorry i didn't read it all ... but i just wanted to say : you rock !!LANG LEVEN to bijstere spoor !
easy chicken fingers recipes o •
What is it, http://soundcloud.com/baked-chicken-recipes baked chicken recipes for you, 22022, http://soundcloud.com/cracker-barrel-restauran cracker barrel restaurant recipes discount, %-]]], http://soundcloud.com/chicken-and-pasta-recipe chicken and pasta recipes, =-]], http://soundcloud.com/easy-chicken-parmesan-re easy chicken parmesan recipes for you, rvw, http://soundcloud.com/easy-low-sodium-recipes First easy low sodium recipes, :]], http://soundcloud.com/quick-shredded-chicken-r Cheapest quick shredded chicken recipes, 8-]], http://soundcloud.com/easter-dinner-recipes easter dinner recipes, 4987, http://soundcloud.com/easy-chicken-fingers-rec easy chicken fingers recipes, %-[[, http://soundcloud.com/thanksgiving-dinner-reci thanksgiving dinner recipes online, =[, http://soundcloud.com/grilled-chicken-recipes grilled chicken recipes free, kmte,