Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
* 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**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
* **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.
* **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](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.
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()](https://developer.mozilla.org/en-US/docs/Web/API/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](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast\_Channel\_API), [Message Channel API](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel), [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame), [setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout), CSS animations, and others.\
XSinator is an automatic tool to **check browsers against several know XS-Leaks** explained in its paper: [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf)\
You can access the tool in [https://xsinator.com/](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.
Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
* **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.
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).
* **Summary:** The \*\*\*\* [**performance.now()**](https://xsleaks.dev/docs/attacks/timing-attacks/clocks/#performancenow) **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**](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceLongTaskTiming) which can identify tasks running for more than 50ms.
* **Code Example**: [https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events](https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events) another example in:
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.
* **Summary:** The [SharedArrayBuffer clock](https://xsleaks.dev/docs/attacks/timing-attacks/clocks/#sharedarraybuffer-and-web-workers) can be used to measure how much time it takes to perform a request. Other clocks could be used.
The [`unload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/unload\_event) and [`beforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload\_event) 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**.
* **Summary:** The [performance.now()](https://xsleaks.dev/docs/attacks/timing-attacks/clocks/#performancenow) API can be used to measure how much time it takes to perform a request. Other clocks could be used.
If a page doesn’t have any [Framing Protections](https://xsleaks.dev/docs/defenses/opt-in/xfo/) 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`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) attribute in the `<iframe>`. This attribute blocks a lot of features including JavaScript execution, which results in almost pure network measurement.
* **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.
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.**URL1**: www.attacker.com/xssearch#try1
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.
* **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.
* **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).**
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.
* **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
Applications often use [postMessage broadcasts](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) 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**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
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.
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 f**urther 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.
JavaScript’s concurrency model is based on a [single-threaded event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) 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 t**akes 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.
* **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**.
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.
* **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.
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. Check what the limit of the browser is, for example 256 global sockets.
2. Block 255 sockets for a long period of time by performing 255 requests to different hosts that simply hang the connection
3. Use the 256th socket by performing a request to the target page.
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.
For more info: [https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/](https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/)
* **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**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
The [`Performance API`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) provides access to performance-related information enhanced by the data from the [`Resource Timing API`](https://developer.mozilla.org/en-US/docs/Web/API/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`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntries) or [`performance.getEntriesByName`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByName) It can also be used to get the execution time using the difference of [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/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.
It is possible to **differentiate between HTTP response status codes** because requests that lead to an **error** do **not create a performance entry**.
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.
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](https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak)
An attacker can detect if a request resulted in an empty HTTP response body because e**mpty pages do not create a performance entry in some browsers**.
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.
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`**.\
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.
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**.
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.
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 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.\
Using the [Performance API](xs-search.md#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](https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources)
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.
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.
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.
* **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.
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**.\
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**.
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.**
The CORP header is a relatively new web platform security feature that when set b**locks 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**.
### CORS error on Origin Reflection misconfiguration <a href="#cors-error-on-origin-reflection-misconfiguration" id="cors-error-on-origin-reflection-misconfiguration"></a>
* **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.
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)**.**\
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.
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**.
* **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.
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**](hacking-with-cookies/cookie-bomb.md)) 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](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended)
According to [Chromium documentation](https://chromium.googlesource.com/chromium/src/+/main/docs/security/url\_display\_guidelines/url\_display\_guidelines.md#URL-Length), 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**.
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**.
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`**.
* **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.
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](https://bugs.chromium.org/p/chromium/issues/detail?id=64309#c113) that allow some control over the content such as `zoom`, `view`, `page`, `toolbar` where this technique could be interesting.
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](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement) leaks the media `duration` and the `buffered` times.
* [HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement) leaks the `videoHeight` and `videoWidth` some browsers may also have `webkitVideoDecodedByteCount`, `webkitAudioDecodedByteCount` and `webkitDecodedFrameCount`
* [getVideoPlaybackQuality()](https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality) leaks the `totalVideoFrames`.
* [HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement) leaks the `height` and `width` but if the image is invalid they will be 0 and [`image.decode()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode) will get rejected.
Web applications may change w**ebsite 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.
Using the CSS [`:visited`](https://developer.mozilla.org/en-US/docs/Web/CSS/:visited) selector, it’s possible to apply a different style for URLs that have been visited.\
Previously it was possible to use [`getComputedStyle()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/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`](https://developer.mozilla.org/en-US/docs/Web/CSS/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.
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.
The `Content-Disposition` header ([`Content-Disposition: attachment`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition)) 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 <a href="#download-bar" id="download-bar"></a>
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.
Another way to test for the [`Content-Disposition: attachment`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) 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**.
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](https://developer.chrome.com/blog/http-cache-partitioning/)\
(Comment from [**here**](https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/))
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**.
* **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.
[**`AbortController`**](https://developer.mozilla.org/en-US/docs/Web/API/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.
* **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**.
1. The attacker registers a service worker in one of their domains (attacker.com).
2. In the main document, the attacker issues a navigation (window.open) to the target website and instructs the Service Worker to start a timer.
3. When the new window starts loading, the attacker navigates the reference obtained in step 2 to a page handled by the Service Worker.
4. When the request performed in step 3 arrives at the service worker, it returns a 204 (No Content) response, which aborts the navigation.
5. 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.
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.
* **Summary:** The [performance.now()](https://xsleaks.dev/docs/attacks/timing-attacks/clocks/#performancenow) API can be used to measure how much time it takes to perform a request. Other clocks could be used.
* **Summary:** The [performance.now()](https://xsleaks.dev/docs/attacks/timing-attacks/clocks/#performancenow) API can be used to measure how much time it takes to perform a request using `window.open`. Other clocks could be used.
Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
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**.
**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:
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**. We do this so the image is not loaded at the beginning.
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](https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e)
If `jQuery(location.hash)` is used, it's possible to find out via timing i**f 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**:
In this section you can find part of the mitigations recommended in [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf) however, there are more mitigations in each section of the wiki [https://xsleaks.dev/](https://xsleaks.dev/). Take a look there for more information about how to protect against these techniques.
* **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**.
* **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 with `SameSite=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**.
* **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.
* 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**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\