The Navigation API is supposed to be a replacement for the old History API. This is supposed to solve the problems of SPA client-side navigations. The navigation.entries() function is used to access a list of the history for a given windows session. Ideally, this will only given history entries for pages that have the same origin as the current page. Each history entry contains the full URL including fragments, making it ripe for attack.
When reading the specification, the author noticed the the API allows for the interception of navigation events. Immediately, the author thought of this as a good potential for abuse. It could be violating SOP, redirecting navigations and more.
The author tried some things but found a post by Gareth Hayes with a tool. Using some ideas from this, they setup an iFrame, setup a hijacker on the iFrame for the navigation API then redirected it to about:blank. Upon doing this, they history array was returned!
The history API would only be returned for items that were sameSite instead of sameOrigin. Still, getting XSS or a subdomain takeover then using this could leak information cross origin, which is pretty bad. For OAuth, which commonly has secrets in the URL, this would be a complete account takeover if somebody visited the website.
They decided to test this with an imaginary XSS on Gitlab forums to the real Gitlab. By having XSS (again, not a real one) on the forums, the OAuth codes could be exfiltrated from the history information of the navigation API. They also learned the difference between a eTLD and a TLD for samesite, which is not talked about as much as it should be.
To really drive home the point, they wanted to find something worse and real to exploit this. codesandbox.io hosts code that can be executed by others on subdomains. If a user was logged in to the site via an SSO provider like Github or Google, an attacker could access the history information with the OAuth codes from the history! Damn, that's real bad. It should be noted that a window reference is all that is needed; either through opening a tab or an iFrame.
The
ticket has some insight into what happened. When copying information for the entries in the
about:blank navigation, the developer did not consider a cross-origin request could be made. Luckily enough,
site isolation (which isolates processes for different origins) prevents leaks cross origin.
Overall, a super interesting vulnerability that actually has some real impact. Following your gut for features that look dangerous works out a lot of the time!