Skip to content

Commit 7d4009c

Browse files
Add CWE to PTART parser (#12068)
* Add CWE fields to test files * Add CWE support to ptart import * Fix bugs related to importing endpoints * Fix bug wherein long filenames on screenshots cause an import to fail * Add comment explaining why filename is truncated --------- Co-authored-by: Hydragyrum <hydragyrum@gmail.com>
1 parent ff09847 commit 7d4009c

10 files changed

+442
-3
lines changed

dojo/tools/ptart/assessment_parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ def get_finding(self, assessment, hit):
5151
if "labels" in hit:
5252
finding.unsaved_tags = hit["labels"]
5353

54+
finding.cwe = ptart_tools.parse_cwe_from_hit(hit)
55+
5456
finding.unsaved_endpoints = ptart_tools.parse_endpoints_from_hit(hit)
5557

5658
# Add screenshots to files, and add other attachments as well.

dojo/tools/ptart/ptart_parser_tools.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from datetime import datetime
33

44
import cvss
5+
from django.core.exceptions import ValidationError
56

67
from dojo.models import Endpoint
78

@@ -96,7 +97,9 @@ def parse_screenshot_data(screenshot):
9697

9798

9899
def get_screenshot_title(screenshot):
99-
caption = screenshot.get("caption", "screenshot")
100+
raw_caption = screenshot.get("caption", "screenshot")
101+
# Screenshot filenames are limited to 100 characters.
102+
caption = f"{raw_caption[:94]}.." if len(raw_caption) > 96 else raw_caption
100103
if not caption:
101104
caption = "screenshot"
102105
return f"{caption}{get_file_suffix_from_screenshot(screenshot)}"
@@ -154,8 +157,17 @@ def get_attachement_title(attachment):
154157
def parse_endpoints_from_hit(hit):
155158
if "asset" not in hit or not hit["asset"]:
156159
return []
157-
endpoint = Endpoint.from_uri(hit["asset"])
158-
return [endpoint]
160+
try:
161+
asset = hit.get("asset", None)
162+
if not asset:
163+
return []
164+
# Workaround for Defect Dojo being silly when parsing uris.
165+
# If there's no protocol, it will assume the hostname is the protocol.
166+
asset = f"https://{asset}" if "://" not in asset else asset
167+
endpoint = Endpoint.from_uri(asset)
168+
except ValidationError:
169+
endpoint = None
170+
return [] if not endpoint else [endpoint]
159171

160172

161173
def generate_test_description_from_report(data):
@@ -185,3 +197,41 @@ def get_transformed_reference(reference):
185197
return url
186198
return None
187199
return f"{title}: {url}"
200+
201+
202+
def parse_cwe_from_hit(hit):
203+
if "cwes" not in hit or not hit["cwes"]:
204+
return None
205+
cwes = hit["cwes"]
206+
# Grab the last CWE in the list, as it's sorted in numerical order,
207+
# and the last element is generally the most specific.
208+
return parse_cwe_id_from_cwe(cwes.pop()) if cwes and isinstance(cwes, list) and len(cwes) > 0 else None
209+
210+
211+
def parse_cwe_id_from_cwe(cwe):
212+
try:
213+
if not cwe:
214+
return None
215+
216+
cwe_id = cwe.get("cwe_id", None)
217+
if not cwe_id:
218+
title = cwe.get("title", None)
219+
if not title:
220+
return None
221+
cwe_id = parse_cwe_id_from_cwe_title(title)
222+
elif isinstance(cwe_id, str):
223+
cwe_id = int(cwe_id)
224+
elif not isinstance(cwe_id, int):
225+
cwe_id = None
226+
except (ValueError, IndexError):
227+
return None
228+
return cwe_id
229+
230+
231+
def parse_cwe_id_from_cwe_title(title):
232+
try:
233+
if not title:
234+
return None
235+
return int(title.split("-")[1])
236+
except (ValueError, IndexError):
237+
return None

dojo/tools/ptart/retest_parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ def get_finding(self, retest, hit):
9191
if "labels" in original_hit:
9292
finding.unsaved_tags = original_hit["labels"]
9393

94+
finding.cwe = ptart_tools.parse_cwe_from_hit(original_hit)
95+
9496
finding.unsaved_endpoints = ptart_tools.parse_endpoints_from_hit(
9597
original_hit,
9698
)

unittests/scans/ptart/ptart_many_vul.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
"A01:2021-Broken Access Control",
4141
"A04:2021-Insecure Design"
4242
],
43+
"cwes": [
44+
{ "cwe_id": 862, "title": "CWE-862 - Missing Authorization" }
45+
],
4346
"screenshots": [
4447
{
4548
"caption": "Borked",
@@ -73,6 +76,9 @@
7376
"labels": [
7477
"A09:2021-Security Logging and Monitoring Failures"
7578
],
79+
"cwes": [
80+
{ "cwe_id": 778, "title": "CWE-778 - Insufficient Logging" }
81+
],
7682
"screenshots": [],
7783
"attachments": [],
7884
"references": []

unittests/scans/ptart/ptart_one_vul.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
"A01:2021-Broken Access Control",
4141
"A04:2021-Insecure Design"
4242
],
43+
"cwes": [
44+
{ "cwe_id": 862, "title": "CWE-862 - Missing Authorization" }
45+
],
4346
"screenshots": [
4447
{
4548
"caption": "Borked",

unittests/scans/ptart/ptart_one_vul_multiple_cwe.json

Lines changed: 75 additions & 0 deletions
Large diffs are not rendered by default.

unittests/scans/ptart/ptart_one_vul_screenshot_long.json

Lines changed: 74 additions & 0 deletions
Large diffs are not rendered by default.

unittests/scans/ptart/ptart_vuln_plus_retest.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
"A01:2021-Broken Access Control",
4141
"A04:2021-Insecure Design"
4242
],
43+
"cwes": [
44+
{ "cwe_id": 862, "title": "CWE-862 - Missing Authorization" }
45+
],
4346
"screenshots": [
4447
{
4548
"caption": "Borked",
@@ -73,6 +76,9 @@
7376
"labels": [
7477
"A09:2021-Security Logging and Monitoring Failures"
7578
],
79+
"cwes": [
80+
{ "cwe_id": 778, "title": "CWE-778 - Insufficient Logging" }
81+
],
7682
"screenshots": [],
7783
"attachments": [],
7884
"references": []
@@ -106,6 +112,9 @@
106112
"labels": [
107113
"A01:2021-Broken Access Control",
108114
"A04:2021-Insecure Design"
115+
],
116+
"cwes": [
117+
{ "cwe_id": 862, "title": "CWE-862 - Missing Authorization" }
109118
]
110119
},
111120
"screenshots": [

unittests/scans/ptart/ptart_vulns_with_mult_assessments.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
"labels": [
4040
"A03:2021-Injection"
4141
],
42+
"cwes": [
43+
{ "cwe_id": 79, "title": "CWE-79 - Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" }
44+
],
4245
"screenshots": [],
4346
"attachments": [],
4447
"references": []
@@ -63,6 +66,9 @@
6366
"A01:2021-Broken Access Control",
6467
"A04:2021-Insecure Design"
6568
],
69+
"cwes": [
70+
{ "cwe_id": 862, "title": "CWE-862 - Missing Authorization" }
71+
],
6672
"screenshots": [
6773
{
6874
"caption": "Borked",
@@ -96,6 +102,9 @@
96102
"labels": [
97103
"A09:2021-Security Logging and Monitoring Failures"
98104
],
105+
"cwes": [
106+
{ "cwe_id": 778, "title": "CWE-778 - Insufficient Logging" }
107+
],
99108
"screenshots": [],
100109
"attachments": [],
101110
"references": []

0 commit comments

Comments
 (0)