Skip to content

Commit 8f0a4a9

Browse files
immuniweb json parser (#12179)
* immuniweb json: domains * immuniweb json * immuniweb json * immuniweb json
1 parent ff97ef9 commit 8f0a4a9

4 files changed

Lines changed: 365 additions & 2 deletions

File tree

docs/content/en/connecting_your_tools/parsers/file/immuniweb.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "Immuniweb Scan"
33
toc_hide: true
44
---
5-
XML Scan Result File from Immuniweb Scan.
5+
XML or JSON Scan Result File from [Immuniweb Scan](https://www.immuniweb.com/).
66

77
### Sample Scan Data
88
Sample Immuniweb Scan scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/immuniweb).

dojo/tools/immuniweb/parser.py

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import hashlib
2+
import json
3+
import logging
4+
from datetime import datetime
25

6+
import dateutil
37
from defusedxml import ElementTree
48

59
from dojo.models import Endpoint, Finding
610

711
__author__ = "properam"
12+
logger = logging.getLogger(__name__)
813

914

1015
class ImmuniwebParser:
@@ -15,9 +20,14 @@ def get_label_for_scan_types(self, scan_type):
1520
return scan_type # no custom label for now
1621

1722
def get_description_for_scan_types(self, scan_type):
18-
return "XML Scan Result File from Imuniweb Scan."
23+
return "XML or JSON Scan Result File from Imuniweb Scan."
1924

2025
def get_findings(self, file, test):
26+
if file.name.lower().endswith(".xml"):
27+
return self.get_findings_from_xml(file, test)
28+
return self.get_findings_from_json(file, test)
29+
30+
def get_findings_from_xml(self, file, test):
2131
ImmuniScanTree = ElementTree.parse(file)
2232
root = ImmuniScanTree.getroot()
2333
# validate XML file
@@ -85,3 +95,68 @@ def get_findings(self, file, test):
8595
finding.unsaved_endpoints.append(Endpoint.from_uri(url))
8696

8797
return list(dupes.values())
98+
99+
def get_findings_from_json(self, file, test):
100+
findings = []
101+
102+
root = json.load(file)
103+
104+
for section in root:
105+
data = root.get(section)
106+
findings.extend(
107+
self.get_findings_from_domains_json(section, data, test),
108+
)
109+
110+
return findings
111+
112+
def get_findings_from_domains_json(self, section, data, test):
113+
findings = []
114+
for item in data:
115+
if not item.get("remediations", []):
116+
continue
117+
118+
# the json contains different types of extra/context information
119+
title = item.get("type", "unknown") + ": " + item.get("name", "unknown")
120+
title += " - " + item["leak_name"] if item.get("leak_name") else ""
121+
date = dateutil.parser.parse(item["discovered"]) if item.get("discovered") else datetime.now()
122+
123+
tag = item["tag"] if item.get("tag") else None
124+
endpoints = []
125+
if item.get("link", None):
126+
endpoints.append(Endpoint.from_uri(item["link"]) if "://" in item["link"] else Endpoint.from_uri("https://" + item["link"]))
127+
if item.get("ip", None):
128+
endpoints.append(Endpoint.from_uri(item["ip"]))
129+
130+
# censor passwords in examples
131+
# this is a bit of a hack, but it's unclear what fields the json can contain
132+
if "examples" in item:
133+
for example in item["examples"]:
134+
if "password" in example:
135+
example["password"] = "REDACTED" # noqa: S105
136+
137+
remediations = item.get("remediations", [])
138+
139+
for remediation in remediations:
140+
description = mitigation = remediation
141+
# the json contains different types of extra/context information
142+
# we just include everything in the description for now as it's unclear which fields are relevant
143+
description += "\n\n"
144+
description += " ## Details\n"
145+
description += "```\n"
146+
description += json.dumps(item, indent=4)
147+
description += "```\n"
148+
149+
finding = Finding(
150+
title=title,
151+
test=test,
152+
date=date,
153+
description=description,
154+
mitigation=mitigation,
155+
severity="Informational",
156+
dynamic_finding=True,
157+
)
158+
finding.unsaved_tags = [tag] if tag else None
159+
finding.unsaved_endpoints = endpoints
160+
161+
findings.append(finding)
162+
return findings
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
{
2+
"domains": [
3+
{
4+
"id": "897984654",
5+
"section": "domains",
6+
"tab": "domains",
7+
"dt": "2021-10-30 23:59:36",
8+
"discovered": "2021-10-30 23:59:36",
9+
"name": "some-company.com",
10+
"link": "https://some-company.com",
11+
"type": "Domain",
12+
"group": "New",
13+
"tag": "",
14+
"parent": 0,
15+
"lastupdatedt": "2025-02-10 12:52:25",
16+
"domain_expiration": "",
17+
"dns_configuration": {
18+
"A": [
19+
"127.0.0.1"
20+
],
21+
"AAAA": [
22+
"2001:1600:4:1e:f816:3fff:feff:ea44"
23+
],
24+
"NS": [
25+
"dns.some-company.com",
26+
"ns1.region.net",
27+
"ns2.region.net"
28+
],
29+
"SOA": [
30+
"dns.some-company.com root.some-company.com"
31+
],
32+
"CNAME": "No issues found",
33+
"DKIM": "DKIM record is missing.",
34+
"DMARC": "DMARC record is missing.",
35+
"SPF": "SPF record is missing."
36+
},
37+
"domain_registrar": "Unknown",
38+
"stats": {
39+
"subdomains": 1,
40+
"websites": 1,
41+
"network": 1,
42+
"repositories": 0,
43+
"incidents": 2
44+
},
45+
"remediations": [
46+
"To prevent spam, email forgery and phishing, configure DKIM, DMARC, SPF DNS records for the domain if it is used to send or receive emails. Additional information is available <a target=\"_blank\" href=\"https://www.exim.org/exim-html-current/doc/html/spec_html/ch-dkim_spf_srs_and_dmarc.html\">here</a>."
47+
]
48+
}
49+
],
50+
"webapps": [
51+
{
52+
"id": "5498677",
53+
"section": "webapps",
54+
"tab": "webapps",
55+
"dt": "2020-11-05 10:46:23",
56+
"discovered": "2020-11-05 10:46:23",
57+
"name": "aai.some-company.com",
58+
"type": "Web",
59+
"group": "Unreachable",
60+
"tag": "",
61+
"link": "aai.some-company.com",
62+
"sld": "some-company.com",
63+
"ip": "",
64+
"fingerprinted_software": [],
65+
"availability": {
66+
"code": 5,
67+
"text": "Closed ports"
68+
},
69+
"status": {
70+
"code": 5,
71+
"text": "Closed ports"
72+
},
73+
"domain_expiration": "",
74+
"http_code": "",
75+
"lastupdatedt": "2025-02-10 10:30:29",
76+
"last_scan": "2025-02-10 10:30:29",
77+
"remediations": [
78+
"SSL/TLS encryption has not been detected when accessing your web application. SSL/TLS encryption is needed to protect the data transmitted between a user’s browser and a web server. It encrypts the data, preventing unauthorized access, helps to verify the identity of websites to protect against impersonation, and ensures data integrity so that it isn’t tampered with during transmission. Enable SSL/TLS encryption on your web application to ensure secure and private communication between your users and your application. This will protect sensitive data, build trust with your visitors, and help comply with security regulations.",
79+
"Deploy a Web Application Firewall (WAF) to protect your website against common web attacks and malicious bots."
80+
]
81+
}
82+
],
83+
"mobileapps": [
84+
{
85+
"id": "6768",
86+
"section": "mobileapps",
87+
"tab": "mobileapps",
88+
"dt": "2024-02-16 06:01:11",
89+
"discovered": "2024-02-16 06:01:11",
90+
"name": "appy",
91+
"type": "iOS",
92+
"group": "Unreachable",
93+
"tag": "",
94+
"link": "https://apps.apple.com/en/app/some-company/id1508498434g3?l=it",
95+
"data": {
96+
"vulns_summary": false,
97+
"scores": false,
98+
"url": "https://apps.apple.com/en/app/some-company/id1508498434g3?l=it",
99+
"appid": "1508498434g3",
100+
"app_id": "1508498434g3",
101+
"app_version": "",
102+
"sca": [],
103+
"rawdata": false
104+
},
105+
"communications": [],
106+
"lastupdatedt": "2025-02-10 09:19:25",
107+
"last_scan": "2025-02-10 09:19:25",
108+
"remediations": []
109+
}
110+
],
111+
"cloud": [
112+
{
113+
"id": "1684534",
114+
"section": "cloud",
115+
"tab": "cloud",
116+
"dt": "2024-07-02 15:23:10",
117+
"discovered": "2024-07-02 15:23:10",
118+
"name": "https://some.site.com",
119+
"type": "SaaS",
120+
"group": "Unreachable",
121+
"tag": "",
122+
"link": "https://some.site.com",
123+
"ip": "3.3.3.3",
124+
"data": {
125+
"cloud": "saas",
126+
"type": "LiveAgent",
127+
"status": "",
128+
"total_objects": "",
129+
"protocol": ""
130+
},
131+
"lastupdatedt": "2025-02-09 17:07:28",
132+
"last_scan": "2025-02-09 17:07:28",
133+
"remediations": []
134+
}
135+
],
136+
"network": [
137+
{
138+
"id": "2458948438",
139+
"section": "network",
140+
"tab": "network",
141+
"dt": "2024-05-25 16:17:41",
142+
"discovered": "2024-05-25 16:17:41",
143+
"name": "52.52.52.52",
144+
"type": "Host",
145+
"group": "",
146+
"tag": "",
147+
"link": "52.52.52.52",
148+
"ip": "52.52.52.52",
149+
"data": {
150+
"black_list": false
151+
},
152+
"vulns": "",
153+
"software": {
154+
"nginx": "nginx"
155+
},
156+
"ports": {
157+
"80": {
158+
"proto": "HTTP",
159+
"banner": "HTTP/1.1 412 Precondition Failed\r\nServer: nginx\r\nDate: Sun, 29 Sep 2024 14:23:55 GMT\r\nContent-Type: text/html\r\nContent-Length: 166\r\nConnection: keep-alive\r\n\r\n",
160+
"extrainfo": "",
161+
"classification": "Web Applications",
162+
"product": "nginx"
163+
},
164+
"443": {
165+
"proto": "HTTPS",
166+
"banner": "",
167+
"extrainfo": "",
168+
"classification": "Web Applications",
169+
"product": "",
170+
"ssl": {
171+
"ssl_port": 443,
172+
"ip": "52.52.52.52",
173+
"valid_to": null,
174+
"compliance_pci_dss": false,
175+
"compliance_nist": false,
176+
"compliance_hipaa": false,
177+
"cert_trusted": false,
178+
"ssl_supported_protocols": [],
179+
"dh_parameter_weak": false
180+
}
181+
}
182+
},
183+
"lastupdatedt": "2024-10-04 14:20:17",
184+
"last_scan": "2024-10-04 14:20:17",
185+
"remediations": []
186+
}
187+
],
188+
"repositories": [
189+
{
190+
"id": "165465138",
191+
"section": "repositories",
192+
"tab": "repositories",
193+
"dt": "2021-02-03 18:38:04",
194+
"discovered": "2021-02-03 18:38:04",
195+
"name": "https://52.52.52.52/.git/",
196+
"type": "Source Code",
197+
"group": "",
198+
"tag": "",
199+
"link": "",
200+
"data": {
201+
"size": 0,
202+
"author": "",
203+
"source": "",
204+
"domain": "",
205+
"link": "",
206+
"sample": ""
207+
},
208+
"lastupdatedt": "2023-03-16 16:43:19",
209+
"last_scan": "2023-03-16 16:43:19",
210+
"examples": [],
211+
"remediations": [
212+
"Local Git code repository is publicly accessible at https://52.52.52.52/.git/. An attacker can exploit the exposed source code and other confidential data available there to compromise your systems or facilitate other attacks. Unless the repository is designed to be accessible from the Internet, urgently disable public access to it. Otherwise, consider implementing a strong authentication and GEO-IP filtering."
213+
]
214+
}
215+
],
216+
"incidents": [
217+
{
218+
"id": "13949496",
219+
"section": "incidents",
220+
"tab": "incidents",
221+
"dt": "2022-09-27 05:41:00",
222+
"discovered": "2022-09-27 05:41:00",
223+
"name": "Stolen Credentials",
224+
"type": "Data Leak",
225+
"group": "Inactive",
226+
"tag": "Legacy",
227+
"link": "",
228+
"data": {
229+
"count": 187,
230+
"domain": "some-company.com",
231+
"record_count": {
232+
"company.com": 1,
233+
"some-company.com": 183,
234+
"test-co.com": 1,
235+
"testing-co.com": 1,
236+
"quick-test.com": 1
237+
},
238+
"leakdt": "2022-05-01"
239+
},
240+
"lastupdatedt": "2024-10-03 19:36:08",
241+
"last_scan": "2024-10-03 19:36:08",
242+
"examples": [
243+
{
244+
"login": "xxxx.yyyyy@domain.ch",
245+
"password": "mypasword1234"
246+
}
247+
],
248+
"examples_type": "LOGINS",
249+
"leak_name": "1.5 GB Corp Mails EU",
250+
"remediations": [
251+
"Accounts of your employees are present in a stolen <a href=\"#\" onclick=\"$('#details_dialog #details_tabs').tabs({active: 0}); setTimeout(function () { $('#details_dialog #details_tabs2').tabs({active: 15}); }, 100); return false;\">set of data</a> available for sale on the Dark Web. Investigate how those accounts were compromised and consider changing the passwords on all accounts of the implicated users. You may also set a canary on your IDS to notify you as soon as someone tries to login to any of your systems with the compromised pair of credentials, thereby evidencing a password spraying attack."
252+
]
253+
}
254+
]
255+
}

0 commit comments

Comments
 (0)