Workflow

Find Reflected XSS on a Domain

Collect a domain's archived URLs, keep parameters that reflect input, and fuzz each one for reflected and DOM cross-site scripting.

100%

Notes on this workflow

Target

A domain. Default scanme.nmap.org. Archived URLs for it and its subdomains are pulled in.

How It Works

Archived URLs are cleaned down to ones that reflect input.

Each parameter is tested for reflected and DOM XSS.

Results

A PDF of XSS findings, plus the URLs that were tested.

Also writes report.json.

Overview

Cross-site scripting survives because the parameter that reflects input is rarely the one anybody documented. It is on a page shipped three years ago, reachable from a link in an old email, still wired to the same template. Testing the application you know about misses it every time.

This works from the application's history instead. You get the archived URL set for a domain, narrowed to the parameters that historically carry reflected values, then fuzzed and confirmed, so what lands in the report is a payload that actually executed rather than a parameter that looks suspicious. Running it after each release turns it into continuous security testing, because the regression you care about is a fix that quietly came undone.

The fuzzing step is distributed, which is what makes a large URL set finish in reasonable time.

Pipeline

  1. Read the target domain.
  2. gau collects archived URLs from public sources.
  3. urldedupe collapses URLs that differ only by parameter value.
  4. gf keeps the ones whose parameters match known XSS patterns.
  5. qsreplace substitutes a probe value into each parameter.
  6. The candidate list is capped so a large archive cannot run away.
  7. dalfox fuzzes each candidate across the fleet and verifies which payloads execute.
  8. Confirmed findings are written to a PDF report.

Inputs

  • Target domain. One domain. You do not supply a URL list, because the whole candidate set is built from the domain's own archived history.
  • Parameter patterns. gf decides which parameters are worth testing using its XSS pattern set. Left alone, that default is what keeps the fuzzer off parameters that have never reflected anything.
  • Candidate cap. The list handed to the fuzzer is capped before it runs, so a domain with a large archive cannot turn one run into an open-ended fuzz. Widen it only when you know the scope can take it.

Outputs

  • A PDF report. Confirmed findings only, each with the parameter, the payload, and the evidence that it executed. A parameter that reflects without executing does not appear, which is what keeps the file short enough to act on.
  • A filtered candidate list. The archived URLs that survived deduplication and pattern matching, which is a reusable target set for other parameter testing.
  • The raw archived URL set. Everything the archive collection step returned for the domain, before any filtering, so you can widen the pattern set and rerun without paying for collection twice.

Sample output

From a completed run against testphp.vulnweb.com, an application published as a deliberately vulnerable test target.

The archive returns far more than is worth testing, which is why the filter runs before the fuzzer. gf kept 66 URLs out of the archived set:

urlparamstage
http://testphp.vulnweb.com/listproducts.php?id=1idarchive
http://testphp.vulnweb.com/listproducts.php?cat=1&page=1cat,pagearchive
http://testphp.vulnweb.com/search.php?order=order&query=queryorder,queryarchive
http://testphp.vulnweb.com/search?q=aaaqarchive
http://testphp.vulnweb.com/bxss/vuln.php?id=FUZZidfuzz-target
http://testphp.vulnweb.com/hpp/params.php?gt=FUZZ&p=FUZZgt,pfuzz-target
http://testphp.vulnweb.com/listproducts.php?cat=1FUZZ&page=1FUZZcat,pagefuzz-target

Those collapse into 55 fuzz targets once qsreplace swaps each value for the marker:

Worth noticing in that list: several archived URLs carry SQL and script payloads in their query strings, because the archive recorded somebody else's scan traffic against this host years ago. The filter treats them as parameters like any other.

dalfox reported nothing on this run. It names the parameter, the payload and the evidence of execution when it does fire, and a parameter that reflects but does not execute is not reported, which keeps the PDF short enough to act on.

FAQ

Does this find stored cross-site scripting?

No. It tests parameters for reflected and DOM cross-site scripting, which is what an archive-and-fuzz approach can reach. Stored requires a value that is saved and then rendered on a later page load, and nothing here does that.

Why archived URLs rather than a crawl?

A crawler sees what is linked today. The archive holds the page that shipped three years ago, is still wired to the same template, and is still reachable from a link in an old email. That is usually where the reflecting parameter is.

How is this different from running dalfox myself?

dalfox needs a candidate list, and building one is the first six steps. This collects the archive, collapses URLs that differ only by parameter value, keeps the ones matching known XSS patterns, then fans the fuzzing across the fleet instead of walking the list one URL at a time.

Is it safe to run against a third party?

Collection reads public archives and sends nothing to the target. Fuzzing does send payloads to the live application, so run the second half only inside a scope that allows active testing, such as a bounty program that lists the domain.

What does a run cost?

The size of the archive sets the ceiling, but not the bill. Deduplication and pattern filtering cut the list before the expensive step and the cap bounds it, so runtime tracks the number of candidate parameters rather than the number of URLs the archive returned.

Get a personalized demo

See Trickest in Action

A 30-minute walkthrough. We map the platform to your stack and answer pricing and deployment questions for your environment.