diff --git a/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md b/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md index 68ac7e7f840..4886a58ab3d 100644 --- a/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md +++ b/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md @@ -11,6 +11,8 @@ This is a **different exploit for the CTF chall** that was already commented in connection-pool-example.md {{#endref}} +This technique is useful when the attacker can create a **Boolean oracle** based on whether a **lazy-loaded image** is fetched or not, but **cannot** directly observe that request because of CSP, `img-src` restrictions, or `Cache-Control: no-store`. Instead of waiting for an external callback, the exploit converts image loading into a **timing side channel** by making those image requests compete with other requests. + The idea behind this exploit is: - The posts are loaded alphabetically @@ -20,6 +22,12 @@ The idea behind this exploit is: - If the **images** injected in the post are being **loaded**, these **fetch** requests will take **longer**, so the attacker knows that the **post is before the flag** (alphabetically). - If the the **fetch** requests are **fast**, it means that the **post** is **alphabetically** **after** the flag. +In other words, the oracle is: + +- **State 1**: the attacker-controlled post is within the browser lazy-loading threshold, so `img loading=lazy` requests are issued. +- **State 2**: the attacker-controlled post remains outside that threshold, so those requests are not issued. +- **Leak**: the attacker measures whether those extra requests create enough contention to delay another measurable operation. + Let's check the code: ```html @@ -154,6 +162,42 @@ Let's check the code: ``` -{{#include ../../banners/hacktricks-training.md}} +## Practical caveats + +This trick is **fragile** and needs to be **calibrated per environment**: + +- The **lazy-loading distance threshold** is browser-dependent and can change with browser version, connection type, and headless/headful mode. Chromium loads off-screen images **before** they are visible, so the right `` is usually found empirically. +- In practice, **headless Chromium** can require a **different threshold** than a normal browser. In the original writeup, a value that worked locally (`1850px`) had to be increased for the remote headless bot (`3350px`). +- Native `loading="lazy"` is only **deferred when JavaScript is enabled**, so this specific oracle can disappear if the browser disables JS or changes lazy-loading behavior for privacy reasons. +- If the image response is **cacheable**, later probes become noisy or useless because the browser may satisfy the request from cache. This is why cache-busting parameters or `Cache-Control: no-store` matter a lot when testing this technique. + +## Reliability notes + +Compared to the related [connection pool example](connection-pool-example.md), this variant does **not** need an external image callback. It only needs a measurable slowdown. That slowdown can come from: + +- **Server-side event-loop blocking**, such as many image requests hitting a Node.js endpoint that performs synchronous work. +- **Socket / connection contention**, where the attacker saturates available connections and times how long an additional request takes. + +To make the oracle more stable: +- Use **multiple lazy images** instead of one. +- Add a **cache-buster** to every image URL. +- Measure **several requests** and compare an **average/median** instead of trusting a single sample. +- Recalculate the **canvas height threshold** against the same browser family and execution mode used by the victim bot. + +For more timing-based leak primitives, also check: + +{{#ref}} +performance.now-+-force-heavy-task.md +{{#endref}} + +> [!WARNING] +> Some privacy-focused defenses can break the "load only after a browser-driven scroll/viewport change" assumption. For example, XS-Leaks wiki documents `Document-Policy: force-load-at-top` as a way to disable load-on-scroll behaviors such as Scroll-to-Text navigation, which can also reduce similar viewport-based oracles. + +## References + +- [https://blog.huli.tw/2022/10/05/en/sekaictf2022-safelist-xsleak/](https://blog.huli.tw/2022/10/05/en/sekaictf2022-safelist-xsleak/) +- [https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img) + +{{#include ../../banners/hacktricks-training.md}}