July 4, 2026
DOM-Based XSS: Three Labs, Three Sinks
DOM XSS Happens when a js takes the attacker input as passes it into a function without proper sanitization.
By CyberForge
2 min read
DOM-Based XSS: Three Labs, Three Sinks
Unlike reflected and stored xss where the attacker has to interact with the server, Dom is different the attacker payload never reaches the server everthing stays in the browser
Source is where you input comes from (location.search, document.url, location.hash)
Sink is where the input lands and gets executed (innerHTML, outerHTML)
Here is the Flow of an attacker controlled input Source Attacker input enters JS (location.search, document.url) JS processes it Sink Input gets written and executed (document.write, innerHTML) Browser Execute Payload
Lab 1: DOM XSS in document.write sink using source location.search
In this lab our search input is the source and document.write is the sink. Our input gets taken from the search query and is passed directly to the document.write, which writes it into the DOM inside an tag specifically landing inside the src attribute like this:
![]()
Since we're already inside the src attribute we need to break out of it first. We inject x", the x completes the src value and the " closes the attribute. Once we're out we add onload="alert(1)" as a new attribute. We used onload instead of onerror because the tracker gif is a real valid path that loads successfully so the image loads and onload fires automatically. Final payload: x" onload="alert(1)"
Lab 2: DOM XSS in innerHTML sink using source location.search
This lab takes our search input and passes it to the innerHTML property, our search input is the source while innerHTML is the sink. Any HTML that reaches innerHTML gets rendered as a real DOM element, but
Lab 3: DOM XSS in jQuery anchor href attribute sink using location.search source
In this lab our input is taken from the returnPath URL parameter that's our source. jQuery reads it and sets it as the href value of the backLink element that's our sink. Since we control the entire href value we don't need to break out of anything. We use javascript:alert(1) as our payload because href accepts javascript: as a pseudo-protocol instead of navigating to a URL, the browser executes whatever follows it as JavaScript. When the back link is clicked our payload fires.
#XSS #WebSecurity #EthicalHacking #PortSwigger #CyberSecurity