Let's begin with this simple URL:
This syntax demonstrates an unintentional and completely impractical quirk in the URL parsing algorithm specified some 16 years ago in RFC 1630. Verbatim implementations are bound to parse this string as a relative reference to
protocol = 'http', host = $base_url.host, path = 'example.com/'. It does not make a whole lot of sense, and indeed, in RFC 3986, Tim Berners-Lee had this to say:
"This is considered to be a loophole in prior specifications of partial URI [RFC1630]. Its use should be avoided but is allowed for backward compatibility."
Fast forward two years: the KDE team is working on a new open-source browser, Konqueror. Their browser uses KURL as the canonical URL parsing library across the codebase. This parser behaves in an RFC-compliant way when handling our weird input string, with one seemingly unimportant difference: if the current parsing context does not have a valid host name associated with it, the address is not rejected as unresolvable; the host name is simply set to an empty string. No big deal, right?
protocol = 'http', host = 'example.com', path = '/'; HTTP cookies and other request parameters are then supplied accordingly.
The result? When you open two windows in Safari - one pointing to
http:hairy-spiders.com, and the other pointing to
http:fuzzy-bunnies.com - the HTTP stack will make sure they are populated with cookie-authenticated data coming from the two different servers named in the URLs; but the same origin checks within the browser will rely on KURL instead. Remember how KURL spews out an empty host name in both cases? Because empty strings always match, both pages are deemed to be coming from the same source, and can access each other at will. Oops.
Well, there's still a catch: this attack will only work as expected if the windows are opened by hand; in documents opened from a web page, the host name from the base URL will interfere with how the URLs are broken down. Thankfully, we can work around it, simply by hopping through a data: URL.
Reported to the vendor in January 2010, fixed in Safari 4.1 and 5.0 (
CVE-2010-0544). A simple and harmless proof-of-concept can be found here.