I’ve been recently reading Michal Zalewski’s “The Tangled Web”, a book which tries to map the whole security landscape around browsers and Web applications in about 300 pages… it does a pretty good job 🙂
document.domain = "example.com";
If both pages first do the same relaxation and then attempt to communicate (e.g. read each others’ cookies, read content in the DOM and add/remove nodes) all is well. Now obviously “foo.example.com” can’t relax its domain to “www.google.com“. The new relaxed domain must be a higher-level domain from where it already is. For the same reason, the page “foo.example.com” can’t relax its domain to “foo.foo.example.com” since that is not really relaxing 🙂
Relaxing more than you should
Now, as a web developer you have about a thousand ways in which you can screw up the security of your site. One of them is to relax your domain too much. What would happen if “foo.example.com” relaxes its domain to “com“? That is a valid higher-level domain after all. Well… there is no good reason for a person to do that, other than a severe misunderstanding of how the whole thing works. For this reason, all modern browsers disallow the setting of document.domain to a TLD value… well, all except Chrome that is.
I decided to make a simple experiment. I resolved locally two domains, myattacker.com and myvictim.com. myattacker.com first relaxed its domain to “com” and then loaded myvictim.com in an iframe which also wrongly relaxes it’s domain to “com”. A short script in myattacker.com attempts to reach in the iframe and read the HTML of the body of the loaded page, containing a secret value. If it succeeds, it dumps the contents of that iframe in its own page.
Testing the browsers
So, we start with Firefox, version 10. Here is a screenshot of the page:
As it should be, Firefox says no and the earth keeps spinning. How about Internet Explorer, the usual black sheep of the web?
Who would have thought? Internet Explorer 8 doesn’t like the thing…
How about Google Chrome (version 18.0.1025.108 beta), the source of all sunny, funny and nice?
Aha! And that’s how the cookie crumbles. Chrome says “sure, go on” and the attacker reaches in the victim’s iframe. Game over! This behavior can also be abused to hack a site that’s vulnerable to XSS. Instead of injecting the full malicious payload, you simply relax its domain and then proceed to inject code which will never be visible at the server-side of the vulnerable Web application, thus making detection and mitigation much harder. More on that, here.
Now why is that, you may ask? These guys implement process per tab, client-side xss filters and what not, to protect the user from harm, even if it is the fault of a specific website. Short answer, I don’t know. The argument that changing it is hard, seems a bit flimsy to me, especially given Google’s prior engineering track record.
Till next time
WAW! Amazing… we expect that all the browsers respect the simple agreements on such trivial things as document.domain assignment, but turns out, the newer browsers (such a Chrome) don’t actually have to comply with such agreement. And legally, they are allowed to do so, since there is no standard that says that assigning to TLD is not allowed! Great findings, Nick!