It has been a month or so since I wrote about
SessionSafe. To my delight a couple of people have taken an interest in the matter. Here is a short summary of the various discussions:
Deferred Loading
There was not a lot of controversy about this topic. Only
Wladimir Palant made some suggestions how to
streamline the implementation. Anyway, as Firefox is about
to implement http-only cookies the need for Deferred Loading slowly vanishes (with Deferred Loading mainly being a http-only implementation for browsers that does not support it natively).
Subdomain Switching
In the original blog entry and in the ph-neutral presentation I hinted that I considered the combination of Deferred Loading and Subdomain Switching to be sufficiently secure.
Kuzza55 brought to my attention that by using anti-dns-pinning and subsequently spoofing the host header with either XHR or the low level socket functions some of the protection provided by Subdomain Switching
can be bypassed (as the authentication cookie for
secure.domain.tld can be sent by the attacker). Therefore, as long not all browsers support http-only cookies and anti-pinning is still an option, we
need one-time URLs.
Besides this, I still consider Subdomain Switching a powerful tool to mitigate the effects of malicious XSS.
One-Time URLs
As I expected, most feedback revolved around the JavaScript trickery that is necessary to hide the random nonces from malicious XSS. At some point during the discussion I posted my
old PoC which spurred even more hacking attempts. It started out with a
watch/unwatch--problem that Kuzza55
found, closely followed by possible caching issues. Then
Kishor found a
silly coding mistake of mine in the PoC. This was succeeded by a
IE and Opera specific technique that required to overwrite the
document-object found by
kazuho, who also found
two additional problems.
Fortunately all of these issues are avoidable and resolved in the PoC. As long as references to all vital resources are kept by the Randomizer in a tamper proof local copy and all values passed to the
go()-function are examined carefully, the one-time-URL concept itself is still feasible. However due to the highly dynamic nature of JavaScript, nobody can foresee wether there are more sneaky ways to trick the Randomizer. I think
kazuho summed it up the best:
Although I agree that it might theoretically be possible to hide a link from XSS, I wonder if its practically possible.
Various bits
During the ongoing work of fixing the PoC, I learned some new aspects of JavaScript:
- Right now, all browser's JS implementations are single threaded. This means a running JS is never interrupted by second script (e.g., because of the triggering of an event). This comes in handy, as race condition based issues are not possible. This also explains the glaring absence of locks/semaphores and related language tools in JS. I do not know if this standardized or if the JS-interpreters behave that way just because the browser's developers could not be bothered to write threading coder. If anyone knows something more precise I would like to learn about it.
- Internet Explorer acts strangely when it comes to redefining certain global objects. If in a single <script>-block the document-element is overwritten it is set to "undefined" even before the redefining instruction is executed. Try this in IE:
alert(document);
var document = "foo bar";
alert(document);
Usually alert(document); results in "[object]" but in this case the first alert results in "undefined". This leaves my kind of puzzled.