Cross-site search (XS-Search) is an important attack principle in the family of XS-Leaks. This type of attack abuses Query-Based Search Systems to leak user information from an attacker origin 12. The original attack uses timing measurements to detect whether or not a search system returns results and works as follows:
Establish a baseline of the time needed for a request to return results (hit), and a baseline for the time needed by a request with no results (miss).
Start a timing attack on the request to the search endpoint, brute-forcing the first character (?q=r).
If the measurement is under the hit baseline, then add one more character (?q=ra); otherwise try a new one (?q=s).
In the end, a full secret (?q=secret) can be leaked.
This attack requires multiple timing measurements to be accurate, something which can be improved with inflation techniques and statistical analysis. Furthermore, instead of brute-forcing letter by letter, attackers can search specific words or sentences to leak only the occurrence of results.
If a page sets its opener property to null or is using COOP protection depending on the users’ state, it becomes possible to infer cross-site information about that state. For example, attackers can detect whether a user is logged in by opening an endpoint in an iframe (or a new window) which only authenticated users have access to, simply by checking its window reference. Run demo
The below snippet demonstrates how to detect whether the opener property was set to null, or whether the COOP header is present with a value other than unsafe-none. This can be done with both iframes and new windows.
Cross-Origin Read Blocking (CORB) is a web platform security feature aimed at reducing the impact of speculative side-channel attacks such as Spectre. Unfortunately, blocking certain types of requests introduced a new type of XS-Leaks 1 that allows attackers to detect if CORB was enforced on one request, but wasn’t on another. Nevertheless, the introduced XS-Leaks are much less problematic than the issues actively protected by CORB (e.g. Spectre).
Cross-Origin Resource Policy (CORP) is a web platform security feature that allows websites to prevent certain resources from being loaded by other origins. This protection complements CORB since it is an opt-in defense, whereas CORB blocks some cross-origin reads by default. Unfortunately, similar to CORB, applications can introduce a new XS-Leak if they misconfigure the use of this protection.
A webpage will introduce an XS-Leak if CORP is enforced based on user data. If a page search feature enforces CORP when showing results, but doesn’t do so when returning no results, an attacker will be able to distinguish the two scenarios. This occurs because a page/resource protected by CORP will return an error when fetched cross-origin. Run demo
When a webpage issues a request to a server (e.g. fetch, HTML tags), the server receives and processes this request. When received, the server decides whether the request should succeed (e.g. 200) or fail (e.g. 404) based on the provided context. When a response has an error status, an error event is fired by the browser for the page to handle. These errors also cover situations where the parser fails, for example when trying to embed HTML content as an image.
Window references allow cross-origin pages to get access to some of the attributes of other pages. These references become available when using or allowing iframe and window.open. The references provide (limited) information about the window as they still respect the same-origin policy.
One of the accessible attributes is window.length which provides the number of frames in the window. This attribute can provide valuable information about a page to an attacker.
Detecting if a cross-site page triggered a navigation (or didn’t) can be useful to an attacker. For example, a website may trigger a navigation in a certain endpoint depending on the status of the user.
To detect if any kind of navigation occurred, an attacker can:
Use an iframe and count the number of times the onload event is triggered.
Check the value of history.length, which is accessible through any window reference. This provides the number of entries in the history of a victim that were either changed by history.pushState or by regular navigations. To get the value of history.length, an attacker changes the location of the window reference to the target website, then changes back to same-origin, and finally reads the value. Run demo
When an endpoint sets the Content-Disposition: attachment header, it instructs the browser to download the response as an attachment instead of navigating to it. Detecting if this behavior occurred might allow attackers to leak private information if the outcome depends on the state of the victim’s account.
Network Timing side-channels have been present on the web since its inception 12. These attacks have had different levels of impact over time, gaining new attention when browsers started shipping high-precision timers like performance.now().
To obtain timing measurements, attackers must use a clock, either an implicit or an explicit one. These clocks are usually interchangeable for the purposes of XS-Leaks and only vary in accuracy and availability. For simplicity, this article assumes the use of the performance.now() API, an explicit clock present in all modern browsers.
Measuring the time of JavaScript execution in a browser can give attackers information on when certain events are triggered, and how long some operations take.
JavaScript’s concurrency model is based on a single-threaded event loop which means it can only run one task at a time. If, for example, some time-consuming task blocks the event loop, the user can perceive a freeze on a page as a result of the UI thread being starved. Other tasks must wait until the blocking task finishes. Each browser implements different process models, which means some web sites might run in different threads (and event loops) depending on their relations.
Some of the factors differ in value depending on the application. This means that Network Timing might be more significant for pages with more backend processing, while Execution Timing can be more significant in applications processing and displaying data within the browser. Attackers can also eliminate some of these factors to obtain more precise measurements. For example, an attacker could preload all of the subresources by embedding the page as an iframe (forcing the browser to cache the subresources) and then perform a second measurement, which excludes any delay introduced by the retrieval of those subresources.