-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should History.length really be cross-domain [XSHM breach]? #2018
Comments
This is the same issue as https://www.owasp.org/index.php/Cross_Site_History_Manipulation_(XSHM) correct? Has any browser taken any steps to mitigate the attack? Checking the demo https://tests.reinom.com/http/xshm/ in Chrome, the malicious page thinks the cookie is set both when it is actually set and when it isn't. |
Yes, it's the same issue. It appears the XSHM occurs in Firefox (47) and IE (11). In Chrome (48), Opera (41), it doesn't. So it may be related to the way History entries are added when a 3xx redirect occurs. I'm not very sure about what the specs says in such situation, so I cannot tell which of (Firefox+IE) or (Opera+Chrome) is wrong about the spec's implementation. |
This is blocked on #1454. Would be interested to hear what @mikewest and @johnwilander think about this one. (Apologies for all the recent pings. I've been looking at older unsolved issues.) |
Not only is this a security/privacy issue, it's also really difficult to manage in a world where nested navigables can be in different processes.
Chrome is currently the only browser that ships other-process iframes, and it's pretty easy to end up with I asked folks what they used Some thoughts on ways forward:
This solves the implementation complexity/races, and the security issues. It will break script that relies on
This solves the implementation races. It doesn't solve the security issues. It will break script that relies on
The following will not modify that value:
This may act inconsistently in browsers that create new event loops for pages that are in the same origin & browsing session. But I'm not sure that's any more inconsistent than I think this solves the implementation complexity/races, and the security issues. It isn't clear to me if this would still break scripts that rely on the current behaviour of Any takers for the above? I'm not trying to "fix" the history API, I'm just trying to resolve the security and race conditions around |
If folks are using |
It would need to be 3 to answer to the question "can I go back and can I go forward". And also if pushState or fragment navigation is used, it would be odd if .length didn't increase. |
Actually, I'm talking shit, just because |
Right, but |
This generic attack is worse than just For example, here is a version that uses You could do a similar thing without Both versions require potentially navigating the child frame which might be a bit destructive for an attacker, but it's possible there are clever ways around that. Of course this attack is also possible using In conclusion, telling when nested browsing contexts navigate is not really hard on the current platform, so I am not sure how concerned we should be. |
I guess maybe I misunderstood the original attack. It's not the fact that the page navigated that we consider sensitive. It's the URL the page navigated to. That can be mitigated, as Chromium has done, by avoiding the same-URL-replace behavior when the initiator is cross-origin: https://bugs.chromium.org/p/chromium/issues/detail?id=1208614 (although I don't think that bug is public). |
I am wondering if there is additional information being revealed by the joint history state compared to listening to onload events from the iframes, beyond the potential URL issue you point to. For example, if a cross-origin iframe were to navigate in a manner that causes the current history entry to be replaced rather than a new one being added, this is something that could be seen through the evolution of the joint history but not by listening to the iframe load events, which I think would be similar in both cases. Additionally, the history API is accessible from iframes I believe, which makes it possible for an iframe to leak data from siblings iframes right? Which wouldn't be possible from just listening to onload callbacks. So overall, it would seem to me that the history API has XSite leak capabilities that go beyond listening to load callbacks. Since it also seems that it is not the most handy API anyway, it would be good if the XSite leak capabilities were mitigated. |
Sort of. It would need to be joined with other information, such as load events, to be distinguishable from the cross-origin iframe doing nothing at all.
Well, you cannot access
Do you have any ideas how to do that? If our goal is not just to protect the URL, but instead to protect any information leakage beyond load events, I think the type of attacks I mentioned in #2018 (comment) where you use |
Current status of History length
As stated in https://html.spec.whatwg.org/multipage/browsers.html#dom-history-length:
This means that the length attribute of the History interface is cross-domain.
Consequence: Cross Site History Manipulation
Generic attack scenario
A webpage can guess the browing history of a nested browing context by keeping a trace of the History length value. As an example, a document can store the value of History length, then open a nested browsing context to another domain, and track the browing actions in that nested browsing context by smartly testing when History length changed.
Online example
An attacker document (called [AD], like https://tests.reinom.com/http/xshm/ ) opens a nested browsing context [NBC] and loads a redirection's target (called [RT], https://dom2.tests.reinom.com/http/xshm/ ) in that [NBC]. Then, [AD] stores the History length value, changes [NBC] URL to a vulnerable page [VP] that does a conditionnal redirection. Once the [NBC] is loaded, the [AD] checks whether History length has changed. If it has not, it means that the [VP] redirected to [RT]. If it has, it means [VP] redirected to another page than [RT] (or did no redirection at all). So [AD] knows whether the redirection from [VP] to [RT] occured (so they knows if the condition of that redirection was true).
Suggested solution
If History length violates the SOP principle, then it can be used to guess informations about a nested browsing context navigation that does not share the same domain-origin. I suggest that the History length attribute should be filtered before being accessed by a Document and only return entries that matches its domain.
Either like the short:
Or the longer but closer to "joint session history" definition ("with all entries ... removed"):
With a link to https://html.spec.whatwg.org/multipage/browsers.html#same-origin-domain on "same origin-domain".
Impact
IMO, the impact this may have is very minor. It will only break reliance on cross domain History, like knowing whether the Document was directly loaded in a browsing context or if it was loaded after clicking a link from another domain. This can still be known with HTTP's Referer header.
But it will break XSHM attacks and enhance privacy security for Web users.
The text was updated successfully, but these errors were encountered: