From 5de225f84988785a0fe16056c4dc068592a850ea Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Sun, 14 Jan 2024 23:49:59 +0100 Subject: [PATCH] :bug: fix #6932, advance qualys for monthly pci scan --- dojo/tools/qualys/csv_parser.py | 86 +++++++++++-------- .../scans/qualys/monthly_pci_issue6932.csv | 2 + unittests/tools/test_qualys_parser.py | 8 ++ 3 files changed, 59 insertions(+), 37 deletions(-) create mode 100644 unittests/scans/qualys/monthly_pci_issue6932.csv diff --git a/dojo/tools/qualys/csv_parser.py b/dojo/tools/qualys/csv_parser.py index 9c28f423f7b..3ea9bcbabc6 100644 --- a/dojo/tools/qualys/csv_parser.py +++ b/dojo/tools/qualys/csv_parser.py @@ -46,7 +46,8 @@ def get_report_findings(csv_reader) -> [dict]: for row in csv_reader: if row.get("Title") and row["Title"] != "Title": report_findings.append(row) - + elif row.get("VULN TITLE"): + report_findings.append(row) return report_findings @@ -108,7 +109,6 @@ def build_findings_from_dict(report_findings: [dict]) -> [Finding]: "5": "Critical", } dojo_findings = [] - for report_finding in report_findings: if report_finding.get("FQDN"): endpoint = Endpoint.from_uri(report_finding.get("FQDN")) @@ -129,44 +129,56 @@ def build_findings_from_dict(report_findings: [dict]) -> [Finding]: if finding_with_id: finding = finding_with_id else: - finding = Finding( - title=f"QID-{report_finding['QID']} | {report_finding['Title']}", - mitigation=report_finding["Solution"], - description=f"{report_finding['Threat']}\nResult Evidence: \n{report_finding.get('Threat', 'Not available')}", - severity=severity_lookup.get(report_finding["Severity"], "Info"), - impact=report_finding["Impact"], - date=parser.parse( - report_finding["Last Detected"].replace("Z", "") - ), - vuln_id_from_tool=report_finding["QID"], - cvssv3=cvssv3 - ) - - cve_data = report_finding.get("CVE ID") - finding.unsaved_vulnerability_ids = ( - cve_data.split(",") if "," in cve_data else [cve_data] - ) + if report_finding.get("Title"): + finding = Finding( + title=f"QID-{report_finding['QID']} | {report_finding['Title']}", + mitigation=report_finding["Solution"], + description=f"{report_finding['Threat']}\nResult Evidence: \n{report_finding.get('Threat', 'Not available')}", + severity=severity_lookup.get(report_finding["Severity"], "Info"), + impact=report_finding["Impact"], + date=parser.parse( + report_finding["Last Detected"].replace("Z", "") + ), + vuln_id_from_tool=report_finding["QID"], + cvssv3=cvssv3 + ) + cve_data = report_finding.get("CVE ID") + # Qualys reports regression findings as active, but with a Date Last + # Fixed. + if report_finding["Date Last Fixed"]: + finding.mitigated = datetime.strptime( + report_finding["Date Last Fixed"], "%m/%d/%Y %H:%M:%S" + ) + finding.is_mitigated = True + else: + finding.is_mitigated = False + + finding.active = report_finding["Vuln Status"] in ( + "Active", + "Re-Opened", + "New", + ) - # Qualys reports regression findings as active, but with a Date Last - # Fixed. - if report_finding["Date Last Fixed"]: - finding.mitigated = datetime.strptime( - report_finding["Date Last Fixed"], "%m/%d/%Y %H:%M:%S" - ) - finding.is_mitigated = True - else: - finding.is_mitigated = False + if finding.active: + finding.mitigated = None + finding.is_mitigated = False + elif report_finding.get("VULN TITLE"): + finding = Finding( + title=f"QID-{report_finding['QID']} | {report_finding['VULN TITLE']}", + mitigation=report_finding["SOLUTION"], + description=f"{report_finding['THREAT']}\nResult Evidence: \n{report_finding.get('THREAT', 'Not available')}", + severity=report_finding["SEVERITY"], + impact=report_finding["IMPACT"], + date=parser.parse( + report_finding["LAST SCAN"].replace("Z", "") + ), + vuln_id_from_tool=report_finding["QID"] + ) + cve_data = report_finding.get("CVEID") - finding.active = report_finding["Vuln Status"] in ( - "Active", - "Re-Opened", - "New", + finding.unsaved_vulnerability_ids = ( + cve_data.split(",") if "," in cve_data else [cve_data] ) - - if finding.active: - finding.mitigated = None - finding.is_mitigated = False - finding.verified = True finding.unsaved_endpoints.append(endpoint) if not finding_with_id: diff --git a/unittests/scans/qualys/monthly_pci_issue6932.csv b/unittests/scans/qualys/monthly_pci_issue6932.csv new file mode 100644 index 00000000000..705abdd5112 --- /dev/null +++ b/unittests/scans/qualys/monthly_pci_issue6932.csv @@ -0,0 +1,2 @@ +IP,HOSTNAME,LAST SCAN,QID,VULN TITLE,TYPE,SEVERITY,PORT,PROTOCOL,OPERATING SYSTEM,IS_PCI,FALSE POSITIVE STATUS,CVSS_BASE,Q_SEVERITY,THREAT,IMPACT,SOLUTION,CVSS_TEMPORAL,CATEGORY,RESULT,BUGTRAQID,CVEID +192.168.0.1,abv.xyw.com.fj,22/09/2022 13:01,86476,Web Server Stopped Responding,POTENTIAL,Medium,80,tcp,Linux 2.x,Fail,Requested,6.4,3,The Web server stopped responding to 3 consecutive connection attempts and/or more than 3 consecutive HTTP / HTTPS requests. Consequently the service aborted testing for HTTP / HTTPS vulnerabilities. The vulnerabilities already detected are still posted. For more details about this QID please review the following Qualys KB article:

,The service was unable to complete testing for HTTP / HTTPS vulnerabilities since the Web server stopped responding.,Check the Web server status.

If the Web server was crashed during the scan please restart the server report the incident to Customer Support and stop scanning the Web server until the issue is resolved.

If the Web server is unable to process multiple concurrent HTTP / HTTPS requests please lower the scan harshness level and launch another scan. If this vulnerability continues to be reported please contact Customer Support.,6.1,Web server,The web server did not respond for 4 consecutive HTTP requests. After these the service was still unable to connect to the web server 2 minutes later.,-, \ No newline at end of file diff --git a/unittests/tools/test_qualys_parser.py b/unittests/tools/test_qualys_parser.py index 498c66c235a..0e758a4f4f0 100644 --- a/unittests/tools/test_qualys_parser.py +++ b/unittests/tools/test_qualys_parser.py @@ -130,3 +130,11 @@ def test_parse_file_with_multiple_vuln_has_multiple_findings_csv(self): self.assertEqual( finding.severity, "Critical" ) + + def test_parse_file_monthly_pci_issue6932(self): + testfile = open( + get_unit_tests_path() + "/scans/qualys/monthly_pci_issue6932.csv" + ) + parser = QualysParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings))