Cross-Site Request Forgery (CSRF): The Complete Practical Guide
CSRF via XSS: Reading the Token and Forging the Request
How an XSS payload defeats a solid CSRF token: read the token from the DOM, submit a valid request in the victim's session, and chain to takeover.
Published
A correct CSRF token stops a request forged from an attacker's page, because that page cannot know the token. CSRF via XSS removes that obstacle entirely: if you can run script in the application's origin, you read the token out of the page and submit a request that validates perfectly. This is the standard answer to "but we have CSRF tokens," and it is why an XSS finding nullifies the CSRF defense. Practice on a free live target.
Why the token stops ordinary CSRF but not this
An anti-CSRF token works by requiring one unpredictable value the attacker cannot guess from outside. A cross-site page is blind to it: the same-origin policy stops the attacker's page from reading the target's pages, so it cannot learn the token. That is the entire protection.
XSS breaks the assumption that the attacker is outside. Your script runs in the origin, so it can read the token the same way the application's own JavaScript does, and then make a same-origin request with it. The token is no longer unpredictable to you, it is right there in the DOM. Every CSRF defense that depends on the attacker being unable to read the page falls at once.
Step 1: confirm script execution
You need an XSS foothold that executes in the target's origin, reflected, stored, or DOM-based. Once your script runs there, it has the victim's session implicitly: any request it makes carries their cookies, and it can read any page the victim can read. The exploitation specifics of getting and using that foothold are in exploiting XSS.
Step 2: read the token from the page
Fetch the page or form that contains the token and parse it out, exactly as the app would. Typically the token sits in a hidden input or a meta tag. Fetch the form page in the victim's session, read the token from the returned DOM, and you now hold a valid token for their session:
1. GET the settings form (same-origin, carries the victim's cookies)
2. Parse the CSRF token value out of the returned HTML (e.g. the hidden input)
3. You now have a valid, session-bound tokenBecause the request is same-origin from within the page, you can read the response, which ordinary CSRF cannot do.
Step 3: submit the state-changing request
Send the state-changing request with the scraped token and the victim's cookies. It passes token validation because the token is genuinely valid for that session, and it passes any SameSite or Referer check because it originates from the page itself:
POST /account/email with the scraped token and [email protected]The server sees a fully legitimate request. From here you chain: change the email, then trigger a password reset to your address, and the account is yours. The same shape adds an API key, promotes a role, or hits any state-changing endpoint the session can reach.
Why this matters for defenders
The lesson is blunt: CSRF tokens, SameSite, and Referer checks all assume the attacker is outside the origin. XSS puts them inside, so none of those defenses apply. "We have anti-CSRF tokens" is never a response to an XSS report, because the XSS reads the token. The only fix for CSRF via XSS is to fix the XSS, which means the CSRF defenses are necessary but not sufficient on their own.
Fixing it
- Eliminate the XSS, which is the actual root cause: contextual output encoding, a strong Content Security Policy, and safe sink usage. See preventing XSS.
- Keep the CSRF token anyway, since it still blocks the far more common cross-site forgery. It is just not a substitute for fixing XSS.
- Set session cookies
HttpOnlyandSameSiteto blunt the payoff of any injection, even though neither stops a script acting from within the session.
Full CSRF defense is in preventing CSRF. For every payload in one place, see the cheat sheet, or chain XSS into a forged request on a free lab.
← Back to Cross-Site Request Forgery (CSRF): The Complete Practical Guide