How does sinks working with dom-based xss
How does sinks working with dom-based xss: Clarify what sources and sinks are in DOM-based XSS, show practical examples for the three main sink categories (Document, Location, Execution), and provide ready‑to‑use payloads plus defenses. • Knowledge • xss, dom
🎯 Objective
Clarify what sources and sinks are in DOM-based XSS, show practical examples for the three main sink categories (Document, Location, Execution), and provide ready‑to‑use payloads plus defenses.
🧩 What I’m covering
- Sink = The reflection point that ultimately executes or helps execute attacker‑controlled input coming from a source.
- DOM-based vulnerability = Untrusted data flows source → sink in the browser (taint-flow), leading to script execution in the victim’s session.
Common easy-to-exploit sinks
eval()document.write()/.innerHTMLsetTimeout()/setInterval()
Common sources
document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
IndexedDB DatabaseCommon vulnerable sinks
document.write()
window.location
document.cookie
eval()
document.domain
WebSocket()
someElement.src
postMessage()
setRequestHeader()
FileReader.readAsText()
ExecuteSql()
sessionStorage.setItem()
document.evaluate()
JSON.parse()
someElement.setAttribute()
RegExp()🧭 Example: Page with 3 sink types
<!DOCTYPE html>
<body>
<p id="p1">Hello, guest!</p>
<script>
var currentSearch = document.location.search;
var searchParams = new URLSearchParams(currentSearch);
/*** Document Sink ***/
var username = searchParams.get('name');
if (username !== null) {
document.getElementById('p1').innerHTML = 'Hello, ' + username + '!';
}
/*** Location Sink ***/
var redir = searchParams.get('redir');
if (redir !== null) {
document.location = redir;
}
/*** Execution Sink ***/
var nasdaq = 'AAAA';
var dowjones = 'BBBB';
var sp500 = 'CCCC';
var market = [];
var index = searchParams.get('index').toString();
eval('market.index=' + index);
document.getElementById('p1').innerHTML = 'Current market index is ' + market.index + '.';
</script>
</body>
</html>📎 Copy‑paste payloads
1) Document Sinks (DOM write APIs)
Sink pattern (unsafe):
document.getElementById('p1').innerHTML = 'Hello, ' + username + '!';Payloads:
https://test.com/tests/sinks.html?name=<img src=x onerror=alert(1)>(Direct <script>alert(1)</script> is often ignored on innerHTML reads; use event handlers like onerror.)
Other doc sinks to watch:
.innerHTML,.outerHTMLdocument.write(),document.writeln()
2) Location Sinks (navigations/loads)
Sink pattern (unsafe):
document.location = redir;Payloads:
https://test.com/tests/sinks.html?redir=javascript:alert(1)Notes:
- Modern browsers often block
javascript:redirects. Historically, data: URIs were used to bypass, but CSP/filters may stop that too.
3) Execution Sinks (direct code execution)
Sink pattern (unsafe):
eval('market.index=' + index);Payloads:
https://test.com/tests/sinks.html?index=alert(1)Other execution sinks:
eval()setTimeout(<string>),setInterval(<string>)- Dangerous template constructions (string‑built code)
🧪 Troubleshooting
- Alert doesn’t fire? You may be in a sink that treats HTML differently (e.g., innerHTML vs. text). Try event‑handler payloads (
<img onerror=...>), or click flows if interaction is needed. javascript:blocked? Expected on modern browsers; try alternative sinks or contexts (e.g., DOM insertion instead of redirection).- CSP present? Strict CSP can block inline JS. Look for allowed sources or different sinks; or prove the issue with a non‑JS payload that demonstrates control (e.g., injected text/attributes).
document.cookieempty? Cookies may beHttpOnly. Usealert(1)to prove code execution regardless.
🔒 Defense (notes)
- Validate & sanitize sources: Never trust
location,URLSearchParams,hash,referrer, storage values, etc. - Avoid dangerous sinks: Prefer safe APIs (
textContentoverinnerHTML; do not useevalor string‑built code). - URL allowlists for navigations (
document.location,someElement.src), blockingjavascript:/data:. - CSP: Use nonces/hashes; avoid
unsafe-inline; disallowdata:andjavascript:where possible. - Template frameworks: Keep default auto‑escaping on; don’t disable it.
- Separate sensitive data from the DOM to minimize exposure.
✅ Key Takeaways
- Document sinks modify the DOM; use event handlers to trigger execution when direct
<script>is ignored. - Location sinks can become open redirects or JS scheme execution points; modern defenses may block them.
- Execution sinks (
eval, timers with strings) directly run attacker input and should be removed or replaced. - DOM‑XSS = taint flow from an untrusted source to an unsafe sink. Block the flow or neutralize the sink.