ffuf Integration with DefectDojo
ffuf Integration with DefectDojo
ffuf ("Fuzz Faster U Fool") is an open source web fuzzer written in Go and maintained by the ffuf project on GitHub. It takes a wordlist and a URL containing a keyword such as FUZZ, substitutes each entry, and reports the requests whose responses pass its matchers and filters. Security teams mostly use it for content discovery: admin paths, forgotten backups, exposed .git directories, and endpoints nobody linked. ffuf writes results as JSON, CSV, HTML, Markdown, and other formats; DefectDojo imports the JSON output.
ffuf Integration with DefectDojo
We run ffuf against our web Assets to find what is reachable that shouldn't be, and we import every run into DefectDojo so those discoveries don't evaporate when the terminal closes. Each hit becomes a Finding with a real endpoint attached, the full ffuf command line preserved as evidence, and a title built from the HTTP status and path. Rescanning the same host doesn't pile up copies, because DefectDojo deduplicates on the title and endpoint, and reimporting tells us which paths have disappeared since the last run.
Why ffuf Matters
Most scanners test the pages they can crawl. ffuf finds the pages that crawlers miss, because it asks for paths by name instead of following links.
- It is fast enough to run large wordlists against many hosts in a single maintenance window.
- Its matchers and filters (status codes, response size, word and line counts) let you tune out the soft-404 pages that make naive brute forcing useless.
- The keyword model is flexible. The same tool fuzzes paths, parameters, headers, and virtual hosts.
- Raw ffuf output is a list of responses with no history. Nobody can tell from the JSON alone whether
/backupshowed up this week or has been exposed since last quarter.
Advantages of This Integration
Running ffuf output through DefectDojo gave us things the JSON file never could:
- Stable deduplication. The ffuf Scan type uses the hash code algorithm on title and endpoints. Response sizes and timestamps live in the description, which is deliberately left out of the hash, so an unchanged target doesn't produce new Findings on every run.
- Hosts stay distinct. Each hit carries the full URL as an endpoint, so fuzzing two hosts with the same wordlist produces separate Findings for each host.
- A lifecycle for exposed paths. Reimporting into the same Test mitigates paths that stopped responding, adds new ones, and reactivates any that come back after a deployment.
- Evidence that survives review. The command line is stored on every Finding. A reviewer can see which matchers and filters decided what counted as a hit without asking the person who ran the scan.
- Triage in one place. Paths that matter get a raised severity, an owner, notes, or a Jira ticket. Paths that are expected get marked as false positives or risk-accepted, and that decision sticks on later imports.
How This Integration Works
DefectDojo imports ffuf results with the ffuf Scan scan type. Only the JSON format is parsed.
1. Run ffuf with JSON output. Use -of json and write the report to a file:
ffuf -u https://target.example.com/FUZZ -w wordlist.txt -of json -o ffuf.json
A clean run is not an empty file. ffuf still writes the command line, a timestamp, and its config block, with an empty results array, and that imports as zero Findings.
2. Import it. In the UI, open the Engagement, choose Import Scan Results, select ffuf Scan, and upload the file. For automation, use the API, which works in Community Edition and DefectDojo Pro:
curl "https://YOUR_INSTANCE/api/v2/import-scan/"
-H "Authorization: Token $DD_API_TOKEN"
-F "scan_type=ffuf Scan"
-F "file=@ffuf.json"
-F "product_name=customer-portal"
-F "engagement_name=Content Discovery"
-F "auto_create_context=true"
DefectDojo Pro users can run the same import from a pipeline with Universal Importer:
universal-importer import
--defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/"
--scan-type "ffuf Scan"
--report-path "./ffuf.json"
--product-name "customer-portal"
--engagement-name "Content Discovery"
--auto-create-context
3. Reimport on a schedule. For a host you fuzz regularly, send later reports to /api/v2/reimport-scan/ against the same Test so the open and closed history of each path stays in one place.
Data Granularity: What Gets Imported
| DefectDojo Field | Source in ffuf Report | Notes |
|---|---|---|
| Title | status and the URL path |
Formatted as HTTP 200: /admin; Discovered: /path if no status |
| Severity | None | Always Info; ffuf reports what exists, not what is wrong |
| Endpoint | url |
Full URL of the hit, so the host is recorded |
| Description | URL, status, wordlist entry | Payload labeled with its keyword when a named keyword is used |
| Description | length, words, lines, content-type |
Response characteristics at scan time |
| Description | redirectlocation |
Included when the response redirected |
| Description | commandline |
The full ffuf command, so matcher and filter choices are visible |
| Finding type | Dynamic | ffuf probes a running service |
| Deduplication | Hash code | Title and endpoints |
The parser drops ffuf's internal FFUFHASH input, which identifies a request for ffuf's replay feature rather than anything about the target.
Use Cases
Before a release goes public: A team runs ffuf against the staging host with a wordlist of common admin, backup, and configuration paths. Anything that responds lands in DefectDojo, where the security engineer raises the severity of the hits that matter and closes the ones that are intentional.
Watching external exposure: A security team fuzzes its internet-facing hosts weekly and reimports into one Test per host. New paths that appear after a deployment show up as new Findings, which is often the first sign that a debug route or a forgotten directory shipped to production.
During a penetration test: A tester imports ffuf results into the client's Engagement alongside findings from other tools. The client gets discovered paths with the command that found them, attached to the right Asset, instead of a pasted terminal log.
Cleaning up legacy hosts: A platform team decommissioning old applications uses repeated ffuf imports to confirm that stale paths actually stop responding. Reimport mitigates each one as it goes away, which leaves an auditable record of the cleanup.
Operational Tips
- Everything imports at Info. Decide up front which path patterns your team escalates (version control directories, backups, admin panels) and adjust severity during triage, so the queue isn't one long list of equal-weight results.
- Tune ffuf's filters before you import. A target that returns 200 for every path will produce one Finding per wordlist entry, and filtering by response size or word count in ffuf is far cheaper than closing those in bulk afterward.
- Use one Test per host and reimport into it. The endpoint keeps hosts distinct, but a per-host Test gives you a clean history of which paths opened and closed.
- Mark expected paths such as
/robots.txtor a public login page as false positives once. Deduplication on title and endpoint means the decision carries forward to later runs. - Tag imports with the wordlist name (for example
tags=raft-medium) so you can tell results from a quick wordlist apart from a deep one. - If you only care about a subset of results, filter in ffuf rather than relying on
minimum_severity. Since every Finding is Info, a severity threshold above Info would drop the whole report.