Skip to content

Commit c65a068

Browse files
🐛 fix gitlab dast to parse request response pair #12050 (#12057)
1 parent e0564ef commit c65a068

3 files changed

Lines changed: 150 additions & 1 deletion

File tree

dojo/tools/gitlab_dast/parser.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ def get_item(self, vuln, test, scanner):
8383
static_finding=False,
8484
dynamic_finding=True,
8585
)
86-
86+
# request response
87+
request, response = self.prepare_request_response(vuln.get("evidence"))
88+
if request is not None:
89+
finding.unsaved_req_resp = []
90+
finding.unsaved_req_resp.append({"req": str(request), "resp": str(response)})
8791
# date
8892
if "discovered_at" in vuln:
8993
finding.date = datetime.strptime(
@@ -125,3 +129,20 @@ def get_item(self, vuln, test, scanner):
125129
finding.mitigation = vuln["solution"]
126130

127131
return finding
132+
133+
def prepare_request_response(self, evidence):
134+
if evidence == []:
135+
return None, None
136+
request = evidence.get("request")
137+
request_headers = request.get("headers", [])
138+
reqHeaders = ""
139+
for header in request_headers:
140+
reqHeaders += " name: " + header["name"] + " | value: " + header["value"] + "\n"
141+
returnrequest = "Request Headers:\n" + str(reqHeaders) + "\nRequest Method: " + str(request.get("method")) + "\nRequest URL: " + str(request.get("url"))
142+
response = evidence.get("response")
143+
response_headers = response.get("headers", [])
144+
respHeaders = ""
145+
for header in response_headers:
146+
respHeaders += " name: " + header["name"] + " | value: " + header["value"] + "\n"
147+
returnresponse = "Response Headers:\n" + str(respHeaders) + "\nResponse Phrase: " + str(response.get("reason_phrase")) + "\nResponse Status Code: " + str(response.get("status_code"))
148+
return returnrequest, returnresponse
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
{
2+
"__comment__": "This is a cut of from the test_api_scan.json",
3+
"vulnerabilities": [
4+
{
5+
"category": "dast",
6+
"confidence": "High",
7+
"cve": "10062",
8+
"description": "The response contains Personally Identifiable Information, such as CC number, SSN and similar sensitive data.",
9+
"discovered_at": "2021-04-23T15:46:40.615",
10+
"evidence": {
11+
"request": {
12+
"headers": [
13+
{
14+
"name": "Accept",
15+
"value": "*/*"
16+
},
17+
{
18+
"name": "Authorization",
19+
"value": "********"
20+
},
21+
{
22+
"name": "Cache-Control",
23+
"value": "no-cache"
24+
},
25+
{
26+
"name": "Content-Length",
27+
"value": "0"
28+
},
29+
{
30+
"name": "Host",
31+
"value": "api-server"
32+
},
33+
{
34+
"name": "Pragma",
35+
"value": "no-cache"
36+
},
37+
{
38+
"name": "User-Agent",
39+
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0"
40+
}
41+
],
42+
"method": "GET",
43+
"url": "http://api-server/v1/trees"
44+
},
45+
"response": {
46+
"headers": [
47+
{
48+
"name": "Accept",
49+
"value": "*/*"
50+
},
51+
{
52+
"name": "Authorization",
53+
"value": "********"
54+
},
55+
{
56+
"name": "Cache-Control",
57+
"value": "no-cache"
58+
},
59+
{
60+
"name": "Content-Length",
61+
"value": "0"
62+
},
63+
{
64+
"name": "Host",
65+
"value": "api-server"
66+
},
67+
{
68+
"name": "Pragma",
69+
"value": "no-cache"
70+
},
71+
{
72+
"name": "User-Agent",
73+
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0"
74+
}
75+
],
76+
"reason_phrase": "OK",
77+
"status_code": 200
78+
},
79+
"summary": "378282246310005; Credit Card Type detected: American Express Bank Identification Number: 378282 Brand: AMERICAN EXPRESS Category: SMALL CORPORATE Issuer: AMERICAN EXPRESS COMPANY"
80+
},
81+
"id": "5ec00bbc-2e53-44cb-83e9-3d35365277e3",
82+
"identifiers": [
83+
{
84+
"name": "PII Disclosure",
85+
"type": "ZAProxy_PluginId",
86+
"url": "https://github.com/zaproxy/zaproxy/blob/w2019-01-14/docs/scanners.md",
87+
"value": "10062"
88+
},
89+
{
90+
"name": "CWE-359",
91+
"type": "CWE",
92+
"url": "https://cwe.mitre.org/data/definitions/359.html",
93+
"value": "359"
94+
}
95+
],
96+
"links": [],
97+
"location": {
98+
"hostname": "http://api-server",
99+
"method": "GET",
100+
"param": "",
101+
"path": "/v1/trees"
102+
},
103+
"message": "PII Disclosure",
104+
"scanner": {
105+
"id": "zaproxy",
106+
"name": "ZAProxy"
107+
},
108+
"severity": "High",
109+
"solution": ""
110+
}
111+
]
112+
}

unittests/tools/test_gitlab_dast_parser.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,19 @@ def test_parse_file_with_multiple_vuln_has_multiple_findings_v15(self):
141141
self.assertEqual(endpoint.port, 80)
142142
self.assertEqual(endpoint.path, "v1/tree/10")
143143
self.assertIn("Ensure that your web server,", finding.mitigation)
144+
145+
def test_parse_file_issue_12050(self):
146+
with open(get_unit_tests_scans_path("gitlab_dast") / "issue_12050.json", encoding="utf-8") as testfile:
147+
parser = GitlabDastParser()
148+
findings = parser.get_findings(testfile, Test())
149+
self.assertEqual(1, len(findings))
150+
# check req/resp
151+
finding = findings[0]
152+
self.assertEqual(1, len(finding.unsaved_req_resp))
153+
req_resp = finding.unsaved_req_resp[0]
154+
self.assertIn("req", req_resp)
155+
self.assertIsNotNone(req_resp["req"])
156+
self.assertIsInstance(req_resp["req"], str)
157+
self.assertIn("resp", req_resp)
158+
self.assertIsNotNone(req_resp["resp"])
159+
self.assertIsInstance(req_resp["resp"], str)

0 commit comments

Comments
 (0)