HackproofHacks
Vulnerability walkthrough · Injection

How to Exploit XSS: A Step-by-Step Lab Walkthrough

14 min read · Lab: DVWA

In one line

XSS is when you get a website to run your JavaScript in someone else's browser, because the site printed your input onto the page without cleaning it first.

What this is, for a beginner

Cross-site scripting happens when an application takes input from a user and writes it into a page without properly encoding it, so the browser interprets the input as code rather than text. When that code is JavaScript, the attacker's script runs in the victim's browser with the victim's session, which is why XSS leads to session theft, account actions performed as the victim, and defacement.

The two classic types are reflected XSS, where the payload is in a request and echoed straight back in the response (often via a crafted link), and stored XSS, where the payload is saved by the app (in a comment or profile) and served to everyone who views that content. Stored is more dangerous because it hits every viewer automatically.

The legal lab we use: DVWA

DVWA has dedicated reflected and stored XSS pages. Run it locally so every payload executes only in your own browser against your own app.

DVWA project page →

Full walkthrough: exploiting it step by step

Step 1 — Open DVWA reflected XSS on Low

Set DVWA Security to Low and open the XSS (Reflected) page, which echoes a name parameter back into the page.

Expected result: The page reflects whatever you type into the name field back onto the page.

Step 2 — Prove the injection with a harmless payload

Enter a simple script payload. On Low it is written into the page unescaped and executes.

name field
<script>alert(document.domain)</script>

Expected result: A JavaScript alert box pops up showing the domain, proving your script executed in the page context.

Step 3 — Demonstrate real impact (cookie access)

Swap the alert for something that shows why XSS matters: reading the document cookies. In a real attack this would be sent to an attacker-controlled server; here you only display it to prove access.

name field
<script>alert(document.cookie)</script>

Expected result: The alert shows the current cookies, demonstrating that your script can read session data the victim's browser holds.

Step 4 — Move to stored XSS

Open the XSS (Stored) page and submit a payload in the message field. Because it is stored, it now executes for anyone who views the guestbook, including you on reload.

message field
<script>alert(document.domain)</script>

Expected result: The alert fires every time the page is loaded, for every viewer, because the payload is persisted server-side.

Step 5 — Raise the difficulty and bypass filters

Set security to Medium and High. Medium often strips <script> naively, which you bypass with alternative vectors such as an image error handler. High tightens filtering further, teaching you encoding and event-handler payloads.

filter-bypass vector
<img src=x onerror=alert(document.domain)>

Expected result: The alternative payload executes even where a naive <script> filter blocks the obvious version, showing why blacklisting fails.

Free resource

Get the free 35-week ethical hacking roadmap

The exact order I'd learn this in, every vulnerability and tool, week by week, with the labs to practise each one. Enter your email and I'll send it over, plus one practical lesson each week.

How to detect and fix this

How to detect it

  • Inject a unique marker into every input and search the response to see where it is reflected and whether special characters are encoded; unencoded output in an HTML, attribute, or script context is likely exploitable.
  • Test stored inputs (comments, profiles, names) as well as reflected parameters, since stored XSS is higher impact and easy to overlook.
  • Consider the output context: the same input may be safe in one place and dangerous in another, so test where the value actually lands.

How to fix it

  • Context-aware output encoding is the primary fix: encode data for HTML, attribute, JavaScript, or URL contexts as appropriate when it is written to the page.
  • Use frameworks that auto-escape by default and avoid dangerous sinks like innerHTML with untrusted data.
  • Deploy a strong Content-Security-Policy as defence in depth so that even an injected script is harder to execute or exfiltrate with.
  • Validate and sanitise on input where a rich format is genuinely needed, using a well-tested sanitiser rather than a homemade blacklist.

Common beginner mistakes

  • Relying only on <script> tags; many contexts require event handlers, attribute breakouts, or other vectors, so learn several.
  • Ignoring output context and wondering why a payload that works in one field fails in another.
  • Treating a blacklist as a fix; encoding, not filtering, is the reliable defence.
  • Testing payloads on sites you do not own instead of DVWA or a PortSwigger lab.

FAQ

What is the difference between reflected and stored XSS?

Reflected XSS is echoed back from a single request, usually delivered via a crafted link, and affects whoever clicks it. Stored XSS is saved by the application and served to everyone who views the affected content, which makes it more dangerous because it needs no per-victim delivery.

What can an attacker actually do with XSS?

Run JavaScript as the victim: steal session tokens, perform actions in the victim's account, capture keystrokes on the page, or deface content. Because it runs with the victim's session, it effectively lets the attacker act as that user on the site.

Does a Content-Security-Policy stop XSS?

A strong CSP is powerful defence in depth that can block or limit script execution and exfiltration, but it is not a substitute for fixing the underlying flaw. Encode output correctly and use CSP on top.

Where to go from here

You just exploited one vulnerability in a lab. Here's the structured path.

Scattered tutorials teach you tricks; they don't make you a pentester. My mentorship is 35 weeks of exactly this, every vulnerability and tool in a deliberate order, on real labs, with one-on-one feedback on your work so your mistakes get caught early instead of becoming habits.

Keep practising