Skip to content

Commit

Permalink
🐛 WFuzz: Generalize severity mapping (#9505)
Browse files Browse the repository at this point in the history
* 🐛 fix wfuzz 301, issue 6182

* make severity mapper more robust

* unittest for missing response code

* update docs
  • Loading branch information
manuel-sommer authored Feb 15, 2024
1 parent c0ac882 commit c1819a1
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 23 deletions.
12 changes: 5 additions & 7 deletions docs/content/en/integrations/parsers/file/wfuzz.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ The return code matching are directly put in Severity as follow(this is hardcode

HTTP Return Code | Severity
-----------------|---------
200 | High
302 | Low
401 | Medium
403 | Medium
404 | Medium
407 | Medium
500 | Low
missing | Low
200 - 299 | High
300 - 399 | Low
400 - 499 | Medium
>= 500 | Low
### Sample Scan Data
Sample Wfuzz JSON importer scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/wfuzz).
33 changes: 17 additions & 16 deletions dojo/tools/wfuzz/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ class WFuzzParser(object):
A class that can be used to parse the WFuzz JSON report files
"""

# table to match HTTP error code and severity
SEVERITY = {
"200": "High",
"302": "Low",
"401": "Medium",
"403": "Medium",
"404": "Medium",
"407": "Medium",
"500": "Low"
}
# match HTTP error code and severity
def severity_mapper(self, input):
if 200 <= int(input) <= 299:
return "High"
elif 300 <= int(input) <= 399:
return "Low"
elif 400 <= int(input) <= 499:
return "Medium"
elif 500 <= int(input):
return "Low"

def get_scan_types(self):
return ["WFuzz JSON report"]
Expand All @@ -32,16 +32,17 @@ def get_description_for_scan_types(self, scan_type):

def get_findings(self, filename, test):
data = json.load(filename)

dupes = {}
for item in data:
url = hyperlink.parse(item["url"])
return_code = str(item["code"])
severity = self.SEVERITY[return_code]
return_code = item.get("code", None)
if return_code is None:
severity = "Low"
else:
severity = self.severity_mapper(input=return_code)
description = f"The URL {url.to_text()} must not be exposed\n Please review your configuration\n"

dupe_key = hashlib.sha256(
(url.to_text() + return_code).encode("utf-8")
(url.to_text() + str(return_code)).encode("utf-8")
).hexdigest()

if dupe_key in dupes:
Expand All @@ -68,7 +69,7 @@ def get_findings(self, filename, test):
)
]
finding.unsaved_req_resp = [
{"req": item["payload"], "resp": str(item["code"])}
{"req": item["payload"], "resp": str(return_code)}
]
dupes[dupe_key] = finding
return list(dupes.values())
13 changes: 13 additions & 0 deletions unittests/scans/wfuzz/one_finding_responsecode_missing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
{
"chars": 2823,
"payload": "/server-status | GET /server-status HTTP/1.1\nContent-Type: application/x-www-form-urlencoded\nUser-Agent: Wfuzz/3.1.0\nHost: example.com\n\n",
"lines": 0,
"location": "",
"method": "GET",
"post_data": [],
"server": "",
"url": "https://example.com/server-status",
"words": 60
}
]
9 changes: 9 additions & 0 deletions unittests/tools/test_wfuzz_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,12 @@ def test_issue_7863(self):
endpoint.clean()
self.assertEqual(1, len(findings))
self.assertEqual("Medium", findings[0].severity)

def test_one_finding_responsecode_missing(self):
testfile = open("unittests/scans/wfuzz/one_finding_responsecode_missing.json")
parser = WFuzzParser()
findings = parser.get_findings(testfile, Test())
for finding in findings:
for endpoint in finding.unsaved_endpoints:
endpoint.clean()
self.assertEqual(1, len(findings))

0 comments on commit c1819a1

Please sign in to comment.