XSS vs CSRF: Key Differences, Examples, and Prevention

Web Security
11 min read
XSS vs CSRF: Key Differences, Examples, and Prevention
On this page
  1. XSS vs CSRF: The Difference at a Glance
  2. What Is XSS (Cross-Site Scripting)?
    1. An XSS Attack Example
  3. What Is CSRF (Cross-Site Request Forgery)?
    1. How a CSRF Attack Works
    2. A CSRF Attack Example
  4. How XSS and CSRF Differ Under the Hood
  5. Can XSS Lead to CSRF?
  6. How to Prevent XSS and CSRF
    1. Preventing XSS
    2. Preventing CSRF
  7. Real-World Impact
  8. How to Test for XSS and CSRF
    1. Practice With Dedicated Labs
  9. Legal and Ethical Considerations
  10. Frequently Asked Questions
  11. Your Next Steps

Two bugs, two very different break-ins. With XSS (cross-site scripting), the attacker gets their JavaScript running inside a trusted page, where it can read anything you can see. With CSRF (cross-site request forgery), the attacker never touches that page at all: their own site quietly makes your browser send a request the target trusts, like "transfer $1,000", and your session cookie does the rest.

That is the whole XSS vs CSRF difference in one breath: XSS is code running inside the target, CSRF is a forged request fired from outside it. Both sit in the OWASP Top 10, and the fastest way to feel the gap is to exploit each once: pop a harmless alert in the XSS Playground lab, then forge a transfer in the CSRF lab linked below. This guide puts both attacks side by side, shows why one can defeat the other's defenses, and covers what actually stops each in 2026.

TL;DR: XSS injects attacker JavaScript into a trusted site, so it can read data, steal tokens and act as the user. CSRF tricks a logged-in browser into sending an unwanted request from another site; it can trigger actions but cannot read the response. Stop XSS with context-aware output encoding and a Content Security Policy. Stop CSRF with anti-CSRF tokens, SameSite cookies and Fetch Metadata checks. If a site has XSS, its CSRF defenses no longer matter.

XSS vs CSRF: The Difference at a Glance

What is the difference between XSS and CSRF? XSS makes the vulnerable site run the attacker's script in the victim's browser, giving it full access to the page. CSRF makes the victim's browser send a request to the vulnerable site from an attacker-controlled page, abusing the fact that cookies ride along automatically. XSS can read and act; CSRF can only act.

Aspect XSS CSRF
Where the attacker's code runs Inside the vulnerable site's page On the attacker's own page
What it abuses The browser's trust in the site's content The site's trust in the user's browser
Needs Unencoded user input rendered in a page A logged-in victim and a predictable state-changing request
Can read responses? Yes No (same-origin policy)
Typical impact Data theft, account takeover, any action the user can take One forged action: transfer, email change, settings change
OWASP Top 10:2025 A05:2025 Injection (CWE-79) A01:2025 Broken Access Control (CWE-352)
Main defenses Output encoding, CSP, HttpOnly cookies CSRF tokens, SameSite cookies, Fetch Metadata

Easy way to remember: XSS is putting words in the site's mouth. CSRF is forging the user's signature.

What Is XSS (Cross-Site Scripting)?

Cross-site scripting happens when an application puts user input into a page without encoding it, so the browser parses that input as HTML or JavaScript instead of showing it as text. The injected script runs under the site's origin, with access to the page, its DOM, its non-HttpOnly cookies and anything the user can do there.

It comes in three flavors, covered in depth in our cross-site scripting guide:

  • Reflected XSS: the payload travels in the request (usually a URL parameter) and is echoed straight back. The victim has to open a crafted link.
  • Stored XSS: the payload is saved (a comment, a profile bio) and served to every visitor. No link needed, which makes it the most dangerous type.
  • DOM-based XSS: the site's own JavaScript writes untrusted data, such as location.hash, into the page. The server may never see the payload.

An XSS Attack Example

A search page echoes the query without encoding it:

<!-- Vulnerable PHP -->
<p>Results for: <?php echo $_GET['q']; ?></p>

Send q=shoes and the page reads "Results for: shoes". Send q=<script>alert(document.domain)</script> and the browser parses that as a real script tag and runs it. The proof is a harmless alert, but the same foothold lets a script read the page and make requests as the logged-in user. If the session cookie is not marked HttpOnly, it can also read that cookie directly, which is why that one flag matters so much.

💻
Practice this now: XSS Playground lab - inject a payload into an unescaped field, watch it execute, and learn which contexts need which breakout. Browser-based, no setup.

What Is CSRF (Cross-Site Request Forgery)?

Cross-site request forgery tricks a logged-in user's browser into sending a state-changing request to a site that trusts it. The attacker's page builds the request, the browser attaches the victim's cookies, and the server sees a valid session and does what it is told. Nothing is injected into the vulnerable site.

How a CSRF Attack Works

  1. The victim logs into bank.example. A session cookie is stored in their browser.
  2. They open the attacker's page in another tab, still logged in.
  3. That page fires a request at bank.example, hidden inside an image tag or an auto-submitting form.
  4. The browser attaches the session cookie automatically, because that is how cookies work for any request to that domain.
  5. The server processes it as legitimate, unable to tell a forged request from a real one.

A CSRF Attack Example

For an endpoint that accepts a GET, a hidden image tag on the attacker's page is enough:

<!-- On the attacker's page -->
<img src="https://bank.example/transfer?to=mallory&amount=1000" style="display:none">

For a POST endpoint, an auto-submitting form does the same job:

<form action="https://bank.example/transfer" method="POST" id="f">
  <input type="hidden" name="to" value="mallory">
  <input type="hidden" name="amount" value="1000">
</form>
<script>document.getElementById('f').submit();</script>

The attack is invisible. The victim loads a page, and the transfer happens with no prompt and nothing unusual on screen. This only works while they have a live session and if the endpoint has no anti-CSRF protection.

How XSS and CSRF Differ Under the Hood

What gets exploited

XSS: the trust the browser places in the site's content. Injected scripts run with the site's full privileges.

CSRF: the trust the server places in the browser's cookies. Any request with a valid session is accepted.

What the attacker gets

XSS: read and write. Steal data, read tokens, rewrite the page, perform any action.

CSRF: write only. Trigger an action, but never read the response.

Where the code runs

XSS: inside the vulnerable site itself.

CSRF: on the attacker's page, aimed at the vulnerable site.

Session dependency

XSS: works logged in or out (a live session makes it more valuable).

CSRF: only works against a live, authenticated session.

Can XSS Lead to CSRF?

Yes, and it is why XSS outranks CSRF in severity. A CSRF token works because the attacker's off-site page cannot read it. But XSS runs inside the origin, so the injected script can read the token straight from the page and attach it to a forged request. The request then looks completely legitimate, token and all.

In other words, an XSS foothold walks straight through CSRF defenses. That is the practical takeaway: if a site has XSS, you effectively have CSRF for free, plus the ability to read data. Fixing CSRF does nothing for XSS, and an unfixed XSS undermines your CSRF controls.

How to Prevent XSS and CSRF

The two need different defenses. CSRF tokens do nothing against XSS, and output encoding does nothing against CSRF. You want both sets in place.

Preventing XSS

  • 🔒 Context-aware output encoding. Escape user data for the exact context it lands in (HTML body, attribute, JavaScript, URL). This is the fix that ends the bug. Let your framework auto-escape and audit every escape hatch like dangerouslySetInnerHTML or raw innerHTML.
  • 🛡️ Content Security Policy. A strict CSP that blocks inline scripts is a strong second layer. It will not fix the bug, but it can stop a payload from executing when one slips through.
  • 🍪 HttpOnly session cookies. Keeps JavaScript from reading the session cookie, neutralizing the most direct form of session theft. Pair with Secure.
  • ✅ Sanitize rich text with a vetted library. If users legitimately submit HTML, run it through DOMPurify rather than a hand-rolled filter.

Preventing CSRF

  • 🎫 Anti-CSRF tokens. Put an unpredictable per-session token in every state-changing form and verify it server-side. An off-site page cannot read or guess it.
  • 🍪 SameSite cookies. SameSite=Lax (the Chrome default since 2020) stops cookies from riding along on most cross-site requests; Strict is tighter. Treat it as defense in depth, not your only control, since it is a browser behavior, not a server check.
  • 🔍 Fetch Metadata and Origin checks. Reject state-changing requests whose Sec-Fetch-Site or Origin header shows they came from another site.
  • 🔐 Re-authenticate for critical actions. Require a password or step-up check for high-value operations like fund transfers.

One-line cheat sheet: XSS defense = encode output + CSP + HttpOnly. CSRF defense = tokens + SameSite + Origin checks.

Real-World Impact

XSS in the wild

Samy worm (MySpace, 2005): a stored XSS worm that added its author as a friend and copied itself to each visitor's profile, hitting over a million accounts in under a day.

Fortnite (2019): Check Point chained an XSS bug on an old Epic Games subdomain with an OAuth redirect flaw to steal login tokens and take over accounts without a password.

CSRF in the wild

ING Direct (2008): researchers Zeller and Felten showed a CSRF flaw that could move money out of a victim's bank account, one of the first published CSRF attacks against a bank.

YouTube (2008): the same research found CSRF in nearly every user action on the site, from adding videos to messaging.

Both attacks keep appearing because the underlying trust they abuse, a browser trusting site content and a server trusting a cookie, is baked into how the web works. See the current rankings in the OWASP Top 10:2025.

How to Test for XSS and CSRF

XSS testing checklist

  • Inject a unique marker in every input, then read the raw HTML to see if it comes back encoded or raw.
  • Where it is raw, shape a payload for that context (body, attribute, script, URL).
  • Test URL parameters, form fields, headers, and anything a single-page app reads from the URL fragment.
  • Prove impact with alert(document.domain), which shows the executing origin.

CSRF testing checklist

  • Check whether each state-changing request carries an anti-CSRF token.
  • Remove or alter the token and see if the server still accepts the request.
  • Replay the request from a different origin without the token.
  • Inspect the cookie's SameSite attribute.

Practice With Dedicated Labs

XSS Playground

Practice reflected, stored, and DOM-based XSS in a safe target, then see output encoding shut each one down.

CSRF Bank Transfer

Forge a transfer against a logged-in session, then add a token and watch the attack stop working.

Critical reminder: Get explicit written authorization before testing any site for XSS or CSRF. Firing payloads or forged requests at systems you do not own is unauthorized access under the Computer Fraud and Abuse Act (US), the Computer Misuse Act (UK), and equivalent laws worldwide, even when the payload is a harmless alert box.

  • Test only on systems you own, on intentionally vulnerable practice targets, or within an authorized bug bounty or engagement scope.
  • Use benign proofs. Do not deploy payloads that read real users' data to demonstrate impact.
  • If you find a bug in someone else's application, report it through their disclosure process and stop there.
  • The labs and courses linked here exist so you can practice both the attack and the defense legally.

Frequently Asked Questions

Is CSRF a type of XSS?

No. They are separate vulnerabilities with different mechanisms and different fixes. XSS runs the attacker's code inside the target site; CSRF sends a forged request to the target from elsewhere. They are related only in that XSS can be used to defeat CSRF protections.

Which is more dangerous, XSS or CSRF?

XSS. It gives an attacker full read and write access inside the user's session, not just the ability to trigger one action, and it can read CSRF tokens to bypass CSRF defenses. CSRF is limited to actions the victim is already authorized to perform.

Can CSRF steal data?

Not directly. Because of the same-origin policy, the attacker's page cannot read the response to a cross-site request. CSRF can make a bank send money but cannot read the account balance. XSS, running inside the origin, can read the response.

Do CSRF tokens prevent XSS?

No. CSRF tokens only stop CSRF. XSS needs its own defenses: context-aware output encoding, a Content Security Policy, HttpOnly cookies, and framework auto-escaping. Worse, XSS can read a CSRF token from the page and use it.

Where do XSS and CSRF sit in the OWASP Top 10:2025?

XSS is part of A05:2025 Injection (CWE-79), the same category as SQL injection. CSRF maps to A01:2025 Broken Access Control (CWE-352). Both remain common findings in modern web applications.

Your Next Steps

The XSS vs CSRF distinction is really one question: is the attacker's code running inside the target, or is a forged request being fired at it from outside? XSS is the inside job, with read and write access and the power to defeat CSRF tokens. CSRF is the outside job, limited to actions the victim can already take. Defend XSS with output encoding and a CSP; defend CSRF with tokens, SameSite cookies and Origin checks; and remember that fixing one does nothing for the other.

Reading about it only gets you so far. Pop a script in the XSS Playground, then forge a transfer in the CSRF Bank Transfer lab. When you want both in the context of the whole web attack surface, the CSRF chapter of our Web Attacks course walks through them alongside SQL injection and the rest of the OWASP Top 10 in guided browser labs. Start with HackerDNA's free tier, no credit card required.

HackerDNA Team

HackerDNA Team

Written by the HackerDNA team - cybersecurity professionals building hands-on hacking labs and educational content to help you develop real-world security skills.

Meet the Team

Ready to put this into practice?

Stop reading, start hacking. Real machines, in your browser, free.

Start Hacking Free
30,000+ Hackers Real labs Free
Start Hacking Free or solve today's hack, no account needed