⚠️ Authorised Lab Environment Only. All XSS cookie theft and session hijacking techniques in this lab must be practised exclusively on your own local DVWA installation or authorised lab platforms like TryHackMe and HackTheBox. Performing these techniques against any external website without explicit written permission violates computer misuse laws. Never target real user sessions. All lab exercises use localhost only.
DVWA XSS cookie theft lab 2026 :— Finding an XSS vulnerability is impressive. Stealing a session cookie with it and logging in as another user is what turns an impressive finding into a critical one. Most beginners who discover XSS stop at the alert box. They prove the injection exists but they don’t demonstrate what an attacker could actually do with it. Triagers see alert boxes every day. What gets a finding escalated to Critical is a working proof-of-concept that shows the victim’s authenticated session being taken over. This lab builds that full chain from scratch — payload injection, cookie exfiltration via listener, and session replay that puts you in the victim’s authenticated account without ever knowing their password.
🎯 What You’ll Master in Lab 19
Understand why session cookie theft transforms XSS from theoretical to critical severity
Set up a cookie listener using Python HTTP server and Netcat
Craft and inject XSS cookie exfiltration payloads at Low, Medium, and High security
Capture a stolen PHPSESSID value and replay it to hijack an authenticated session
Understand the HttpOnly flag and why it specifically blocks document.cookie-based theft
Build a stored XSS cookie theft payload that hits every visitor automatically
⏱️ 50 min lab · 3 terminal exercises · Localhost DVWA only
📋 Prerequisites — Complete Before Lab 19
Lab 8: DVWA XSS Reflected — understand how reflected XSS payloads inject and execute before attempting cookie theft
Lab 9: DVWA XSS Stored — stored XSS combined with cookie theft is more dangerous; understand both attack types
Lab 10: DVWA DOM XSS — DOM-based XSS uses a different code execution path; completing the full XSS trilogy before Lab 19 is recommended
Labs 8, 9, and 10 established how XSS payloads inject and execute across reflected, stored, and DOM contexts. Lab 8’s reflected XSS showed that user input reaches the browser unescaped. Lab 9’s stored XSS showed that payloads persist and hit every visitor. Lab 19 completes the XSS attack chain by weaponising those injection points for the most impactful outcome: stealing the authenticated session of anyone who loads the vulnerable page. Once you complete this lab, the DVWA Lab Series moves to Lab 20’s CSRF Advanced — where XSS and CSRF chain together for an even more powerful combined attack.
Why Session Cookies Are the Target — Account Takeover Without a Password
Web applications maintain authentication state through session cookies. When you log in, the server creates a unique session identifier — typically stored in a cookie named PHPSESSID, JSESSIONID, session_id, or similar — and sends it to your browser. Every subsequent request your browser makes to the server includes this cookie in the header. The server checks the cookie against its session store and knows who you are. The session cookie is your authentication credential for the duration of the session.
This architecture has a critical implication for XSS: if an attacker can execute JavaScript in your browser’s context on the target application’s domain, they can read your session cookie using document.cookie and send it to any server they control. The attacker then injects that cookie value into their own browser and — from the server’s perspective — they are now you. No password required. No MFA bypass required. No account recovery needed. They have your session token, and that token grants full access to your account for as long as the session remains valid.
This is precisely why XSS vulnerabilities on authenticated pages are rated Critical in most vulnerability assessment frameworks. The theoretical “attacker could execute arbitrary JavaScript” becomes concrete the moment you demonstrate session cookie theft and account takeover. In bug bounty programmes, an XSS finding with a working cookie theft PoC earns dramatically higher payouts than an XSS finding with only an alert box demonstration — because the impact chain is undeniable.
Lab Setup Reminder: Ensure DVWA is running at http://localhost/dvwa/ and you are logged in as admin. Open a second browser profile or incognito window to simulate the victim user — you will use this to demonstrate that the stolen cookie from “admin” successfully authenticates in the attacker’s browser. This two-browser setup makes the account takeover demonstration concrete and is exactly what you would include in a real bug bounty PoC.
securityelites.com
Session Cookie Architecture — What the Attacker Is Targeting
NORMAL REQUEST (Authenticated User)
GET /dvwa/index.php HTTP/1.1
Cookie: PHPSESSID=a1b2c3d4e5f6
→ Server: session valid → show admin content
ATTACKER REQUEST (Replayed Cookie)
GET /dvwa/index.php HTTP/1.1
Cookie: PHPSESSID=a1b2c3d4e5f6 ← stolen!
→ Server: session valid → show admin content ❌
The server cannot distinguish between the real user and an attacker replaying their session token
📸 Session cookie architecture from the attacker’s perspective. The server validates the PHPSESSID value — not the requester’s identity, IP address, or browser fingerprint. When an attacker steals the session token via XSS and replays it, the server sees a valid session ID and grants full access. This is why session cookies are the primary target of XSS exploitation and why HttpOnly flag and short session expiry are essential security controls.
Setting Up the Cookie Listener on Kali
Before injecting any payload, you need a server running on your Kali machine that can receive the stolen cookie. When the XSS payload fires in the victim’s browser, it makes an HTTP request to your listener with the cookie value as a URL parameter. Your listener logs that request, you extract the cookie value, and you replay it. The listener is the simplest component of the attack — a single Python or Netcat command — but it must be running before you inject, because the payload fires the moment the victim loads the page.
Two options work well for this lab: Python’s built-in HTTP server and Netcat. The Python server provides cleaner output and automatically URL-decodes the request parameters, making the cookie value immediately readable. Netcat gives you raw request data and is more representative of how you’d receive exfiltrated data in a real scenario where the victim’s browser might send more complex cookie strings. For DVWA’s simple PHPSESSID, both work equally well.
LISTENER SETUP — PYTHON HTTP SERVER AND NETCAT
# Get your Kali machine’s IP address
ip a | grep “inet ” | grep -v “127.0.0.1”
inet 192.168.56.100/24 brd 192.168.56.255 scope global eth1
# Note: 192.168.56.100 — this is your LHOST in all payloads
# For localhost DVWA labs, use 127.0.0.1 as LHOST
# Option A: Python HTTP server (recommended — clean output)
mkdir -p /tmp/cookie-lab && cd /tmp/cookie-lab
python3 -m http.server 8888
Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) …
# Step 2: In your browser, log in to DVWA as admin/password
# Set DVWA security level to LOW
# Navigate to: DVWA > XSS (Reflected)
# Step 3: Confirm cookies are readable via JS — test payload first
# In the “What’s your name?” field, enter:
<script>alert(document.cookie)</script>
# An alert box should appear showing: PHPSESSID=xxxxxx; security=low
# If you see this: XSS executes + cookies are readable = theft is viable
# Step 4: Check DVWA cookie HttpOnly status in browser DevTools
# F12 > Application > Storage > Cookies > http://localhost
# Find PHPSESSID row — check HttpOnly column
# In default DVWA: HttpOnly = false → cookie is readable via document.cookie
# Step 5: Note your current PHPSESSID value for comparison
echo “My session before theft: [copy PHPSESSID value here]”
✅ What you just learned: The alert(document.cookie) test is the critical viability check before attempting theft. If the alert shows the PHPSESSID, two conditions are confirmed: (1) XSS executes, (2) the cookie has no HttpOnly flag. Both are required for document.cookie-based theft. If the alert shows an empty string or only the security cookie, HttpOnly is set and the direct theft chain won’t work. In DVWA’s default configuration, HttpOnly is intentionally disabled so the full attack chain is demonstrable. Note that the “security=low” cookie also appears — DVWA uses this to track the security level setting.
📸 Screenshot the alert box showing your PHPSESSID. Post to #lab-19-cookie-theft on Discord. This is your baseline before the theft.
Low Security — Cookie Exfiltration Payload
At DVWA Low security, there is no filtering of any kind on the name parameter. Any JavaScript you inject executes directly. The cookie exfiltration payload redirects the victim’s browser to your listener with the cookie value as a URL parameter. When the browser follows the redirect, your listener receives an HTTP GET request containing the full cookie string as part of the URL. The payload uses document.location for the redirect — this is equivalent to navigating the browser programmatically and triggers the GET request automatically without any alert box or visible indicator to the victim.
The anatomy of the payload is worth understanding in detail. document.location sets the browser’s current URL to whatever value you assign. By setting it to your listener’s URL with document.cookie appended as a query parameter, the browser makes a GET request to your server that includes the full cookie string. The + operator concatenates the base URL with the cookie value. The result is a clean, reliable exfiltration that works across all modern browsers and does not produce any visible effect in the page — the victim’s view flickers briefly as the page redirects, but from a social engineering perspective, that page can be designed to redirect back to a convincing landing page immediately after the theft completes.
LOW SECURITY — COOKIE EXFILTRATION PAYLOADS
# Replace LHOST with your Kali IP (or 127.0.0.1 for localhost labs)
✅ PHPSESSID captured: 7f3a2b1c9d8e4f5a — ready for session replay
📸 Cookie exfiltration chain at Low security. The Image payload fires silently in the background — no page redirect, no alert, nothing visible to the victim. The Python listener receives the GET request with the full cookie string as the query parameter. The PHPSESSID value (7f3a2b1c9d8e4f5a in this example) is extracted from between “PHPSESSID=” and the semicolon separator. This value is all you need to impersonate the victim’s authenticated session.
Session Replay — Logging In as the Victim
You have the PHPSESSID. Now you need to inject it into your browser so the server treats your requests as coming from the victim’s authenticated session. The browser sends cookies automatically based on the values stored in its cookie store for a given domain. If you replace your own PHPSESSID with the stolen one, the next request you make to DVWA will include the victim’s session token — and the server will grant you the victim’s access level.
The most reliable method for cookie injection in a testing environment is browser developer tools. Every modern browser provides a cookies panel in the Application or Storage inspector where you can directly edit cookie values without needing any extensions. For more advanced scenarios — automated session replay, integration with Burp Suite, or scripted account takeover demonstrations — you can set cookies programmatically via JavaScript in the console or use Burp’s cookie jar management.
SESSION REPLAY — INJECTING STOLEN COOKIE IN BROWSER
# Method 1: Browser DevTools (fastest for lab demos)
# 1. Open a new browser profile or incognito window
# 2. Navigate to http://localhost/dvwa/
# 3. Open DevTools: F12
# 4. Application tab > Cookies > http://localhost
# 5. Find PHPSESSID row, double-click Value column
📸 Session replay confirmation. The same PHPSESSID value appears in both the victim’s browser (where it was legitimately issued on login) and the attacker’s browser (where it was injected after theft). Both sessions are authenticated as admin. The curl command verifies the same from the terminal — a clean one-liner that confirms account takeover and is ideal for including in a bug bounty PoC screenshot alongside the listener receipt.
Medium Security — Bypassing Script Tag Filters
DVWA Medium security applies basic input filtering that strips or encodes <script> tags. The filter checks for the literal string “<script” and removes it from input. This approach is fundamentally flawed because JavaScript can execute through many HTML elements beyond script tags. Event handlers — the JavaScript attributes attached to HTML elements — execute code when triggered by user or browser events, with no script tag required.
The most reliable event handlers for XSS injection bypass are: onerror on an image element with an invalid src (the error fires immediately without any user interaction), onload on an img, body, or svg element, and onfocus with autofocus attribute. The onerror handler is particularly effective because it fires automatically when the browser tries to load an image and fails — making it a zero-interaction payload that fires the moment the page loads, exactly like a script tag would.
MEDIUM SECURITY — EVENT HANDLER BYPASS PAYLOADS
# Script tags are stripped — use event handlers instead
# Payload 1: img onerror (fires automatically — no interaction)
✅ What you just learned: The two-browser setup mirrors a real attack scenario: window 1 is the victim user (logged-in admin), window 2 is the attacker (initially unauthenticated). After injecting the payload in window 1 and replaying the cookie in window 2, the attacker’s window shows admin access — full account takeover complete. This is the exact demonstration you would include in a bug bounty report to prove impact. Notice that switching to Medium security generates a new PHPSESSID — each login session gets a fresh token. This means the attack must be performed against the victim’s active session, not a stale one.
📸 Screenshot both windows side by side: victim’s DVWA session (Low) and attacker’s window showing admin logged in after cookie replay. Post to #lab-19-cookie-theft on Discord.
High Security — Advanced Bypass Techniques
DVWA High security applies stricter input filtering, typically using a combination of htmlspecialchars() and more aggressive pattern matching that blocks common event handler attributes. The reflected XSS page at High security in DVWA is significantly harder to bypass than Medium — in many DVWA versions, the reflected XSS is effectively patched at High, and the lesson shifts to understanding why the stored XSS page may still be vulnerable even when reflected is secured. This is a realistic model of real applications, which often patch specific injection points without a consistent application-wide security model.
At High security, if input filtering is applied properly, your approach shifts to DOM-based XSS sources and sinks, or to exploiting any stored input paths that may use different sanitisation logic. The DVWA High security XSS Stored page is often still vulnerable to payloads that bypass the character limit by editing the HTML directly in DevTools — changing the maxlength attribute of the input field to allow longer payloads, then injecting an SVG onload or a carefully crafted DOM manipulation payload.
HIGH SECURITY — ADVANCED XSS BYPASS APPROACHES
# High security often restricts character input length
# Bypass maxlength restriction via DevTools HTML edit
# Every user who loads the guestbook page fires the payload
⚠️ HttpOnly Defeats document.cookie Theft: If a session cookie has the HttpOnly flag set, JavaScript cannot read it via document.cookie — the property returns an empty string or omits the protected cookie. This directly breaks the exfiltration payload. At DVWA High security (and in properly configured production applications), HttpOnly should be set on session cookies. When HttpOnly is present, XSS still has impact — keylogging, form hijacking, CSRF token theft — but the direct document.cookie exfiltration chain does not work. Always check HttpOnly status before building a cookie theft PoC.
Stored XSS Cookie Theft — Zero Interaction Required
The most impactful variant of XSS cookie theft combines the exfiltration payload with a stored XSS injection point. When a cookie theft payload is injected into a persistent storage location — a guestbook, a message board, a user profile field, a product review — every user who loads the page containing that payload automatically fires the theft without any additional interaction beyond loading the page. No phishing link. No social engineering. Just a stored payload that silently exfiltrates every visitor’s session token to your listener.
In DVWA’s XSS Stored lab (Lab 9), you injected persistent payloads into the guestbook’s message field. The same guestbook is accessible here. By injecting a cookie theft payload into the message field — with the maxlength restriction bypassed via DevTools — you create a persistent trap that fires for every subsequent visitor who loads the guestbook page. In a real application, this is the difference between finding a bug and demonstrating a mass account takeover scenario that affects every user simultaneously.
⚡ EXERCISE 3 — KALI TERMINAL (15 MIN)
Stored XSS Cookie Theft — Persistent Payload That Hits Every Visitor
⏱️ 15 minutes · Kali + local DVWA · Security level: Low
✅ What you just learned: The stored XSS cookie theft demonstrates why stored XSS is rated more severely than reflected XSS in most security frameworks. With reflected XSS, you must deliver a crafted link to each victim individually. With stored XSS, one injection hits every user who visits the page — mass account takeover with zero per-victim interaction. In a real application this could mean thousands of user sessions being exfiltrated in the hours between a stored payload being injected and a security team discovering and removing it. This is the impact argument that turns a stored XSS finding into a Critical severity report with a high payout.
📸 Screenshot showing both your cookie AND the victim’s cookie appearing in the listener from loading the guestbook page. Post to #lab-19-cookie-theft on Discord with tag #lab19-complete.
🧠 QUICK CHECK — Lab 19 XSS Cookie Theft
You’ve found a stored XSS vulnerability in a web application’s comment field. You inject a cookie theft payload and it fires. But the listener receives: “GET /steal?c=lang=en HTTP/1.1” — the PHPSESSID is missing. What is the most likely cause?
You can now perform the full XSS cookie theft chain: inject payload, capture session token, replay to hijack account. Lab 20 builds directly on this — DVWA CSRF Advanced chains with XSS to extract anti-CSRF tokens and bypass server-side request forgery protections.
XSS cookie theft is an attack where a Cross-Site Scripting vulnerability executes JavaScript that reads the session cookie via document.cookie and exfiltrates it to an attacker server. The attacker replays the stolen token to impersonate the victim’s authenticated session — full account takeover without knowing their password. It is the most impactful exploitation of XSS vulnerabilities on authenticated pages.
What does the DVWA XSS cookie theft lab teach?
Lab 19 builds the complete theft chain: setting up a listener, crafting exfiltration payloads for Low/Medium/High security, capturing the PHPSESSID from the listener output, and replaying it for session hijack. It also covers the HttpOnly flag — the most targeted control against this specific attack — and stored XSS as the mass-account-takeover variant.
What stops XSS cookie theft?
HttpOnly flag on session cookies is the most direct protection — it prevents JavaScript from reading the cookie via document.cookie. CSP restricts where JavaScript can make requests. Proper output encoding prevents the XSS injection in the first place. In DVWA’s default configuration, HttpOnly is disabled intentionally so the full attack is demonstrable.
Is the PHPSESSID HttpOnly in DVWA?
By default, no. DVWA intentionally leaves HttpOnly unset so the cookie theft lab works end-to-end. Real applications should always set HttpOnly and Secure on session cookies. You can verify in DevTools: Application > Cookies > look for the HttpOnly checkbox in the PHPSESSID row.
Can stored XSS steal cookies without the victim clicking anything?
Yes — stored XSS cookie theft fires automatically when the victim loads any page containing the persistent payload. No phishing link, no user interaction beyond navigation. This is why stored XSS with cookie theft on a high-traffic page is rated Critical — it can silently exfiltrate thousands of session tokens.
What DVWA labs come before and after Lab 19?
Lab 18 covered File Upload Advanced. Lab 19 covers XSS Cookie Theft. Lab 20 covers CSRF Advanced — token bypass via XSS, which directly builds on the XSS session context from this lab. Labs 8, 9, 10, and 19 together complete the full DVWA XSS sequence.
← Previous
Lab 18: DVWA File Upload Advanced
Next →
Lab 20: DVWA CSRF Advanced Lab
📚 Further Reading
DVWA XSS Stored Lab — Lab 9— The persistent XSS injection point used in Exercise 3 — stored payloads in the guestbook combine with cookie theft for mass session exfiltration without any victim interaction beyond page load.
DVWA CSRF Advanced Lab — Lab 20— Builds directly on Lab 19 — uses XSS to extract anti-CSRF tokens and bypass server-side request forgery protections for one-click authenticated action attacks.
DVWA Lab Series Hub— Full 30-lab series overview — Lab 19 sits at the intersection of the XSS sequence (Labs 8–10, 19) and the exploitation chain that continues through CSRF Advanced (Lab 20) and SQL Injection High (Lab 21).
PortSwigger XSS Cookie Steal Lab— PortSwigger’s guided XSS cookie theft lab in a realistic application context — complements DVWA Lab 19 with a different injection surface and exploitation approach.
OWASP Session Hijacking Attack Reference— The definitive OWASP reference on session hijacking — covers all vectors including XSS cookie theft, network sniffing, and session fixation with prevention guidance for each.
ME
Mr Elite
Owner, SecurityElites.com
The moment this lab clicked for me was when I first used a stored XSS cookie theft payload on a test application and watched three separate user sessions arrive in my listener within two minutes — each one a different person loading the same page. I hadn’t sent anyone a link. I hadn’t done any social engineering. I just injected the payload once and waited. That’s when the abstract concept of “stored XSS is more dangerous than reflected” became viscerally real. The listener filling up with session tokens while I sat there doing nothing is the most effective demonstration of why XSS severity ratings are not theoretical — they map directly to real-world account takeover at scale.