DOM XSS

Plant a payload in a URL hash, watch it fire client-side, then swap innerHTML for textContent.

What Is DOM XSS?

DOM-based XSS is the kind of XSS the server never sees. The payload lives in a part of the page that never travels in the HTTP request, the URL fragment after #, document.referrer, or postMessage data, and client-side JavaScript pipes it into a dangerous DOM sink like innerHTML, eval, or document.write. WAFs and server-side input filters are blind to it. This exercise puts you on both sides. As Bob, an attacker after logged-in sessions, you use an internal note-sharing tool at Tideline Federal whose viewer renders the URL fragment via innerHTML. You pack an img onerror payload into a share link and email it to a Tideline engineer. As Alice, that engineer, you open the shared note and a popup fires against your own session the moment the page loads. You trace it to the client-side viewer code and ship the fix: write the note with textContent instead of innerHTML so the browser sets a text node instead of parsing HTML, then prove it on staging. The exercise closes with quiz questions on what makes DOM XSS different from Reflected and Stored XSS, why the server-side WAF can't see it, and why swapping the sink is the right fix.

What You'll Learn in DOM XSS

DOM XSS — Training Steps

  1. Open the note-sharing tool

    Today Bob is targeting Tideline Federal, whose staff pass around quick notes through an internal sharing tool. You write a note, the tool hands you a link, and anyone who opens the link reads the note in their browser. Bob opens the composer to see how a note becomes a link.

  2. Share a normal note

    First, Bob shares an ordinary note to see how the tool builds a link. Whatever he writes gets packed into the link itself.

  3. The note rides in the link

    There's the share link. The whole note sits inside it, in the part after the # . When someone opens the link, the viewer reads that fragment and renders it. Nothing about the note ever reaches Tideline's server.

  4. Craft a test payload

    The viewer drops whatever the note contains into the page as HTML. So Bob writes a note that is not really a note: an image tag whose source cannot load, carrying an onerror handler. When the image fails, the handler runs, and any code it holds executes in the browser of whoever opens the link. He starts with the simplest possible proof, a plain alert(1) , just to confirm his code runs at all.

  5. Test the payload

    Before he weaponizes anything, Bob previews his own link to check that the payload fires. Preview opens the note exactly the way a recipient would see it. The moment the viewer loads it, the alert pops. His code runs in the browser, exactly as planned.

  6. Weaponize it

    The proof works, so now Bob makes it dangerous. He goes back to the composer and swaps the harmless alert for a line that reads the visitor's session cookie, the token that keeps them signed in. A real payload would ship that cookie to his own server without a sound. Here it pops the stolen value into view so you can see exactly what it captures.

  7. Send the link to a victim

    Bob emails the weaponized link to Alice, a Tideline engineer who opens shared notes all day. It is dressed up as a note shared ahead of her morning review, so she has no reason to hesitate.

  8. A shared note arrives

    Bob's email is on its way. You own the note-sharing tool's viewer code, and a shared note lands in your inbox right before your 10:00 review. Open it, then open the note.

  9. Open the shared note

    Nothing looks off, so you open the note the way you open dozens of others.

  10. The note steals your session

    The instant the note loaded, this popup fired in your browser, and it is showing your own session cookie, the token that keeps you signed in. You clicked nothing and typed nothing. The shared note carried a script, and it just read your session and could have shipped it straight to an attacker. That is a full account takeover from opening one link.