Skip to content

Commit 9776af0

Browse files
committed
udpate
1 parent 3228884 commit 9776af0

1 file changed

Lines changed: 0 additions & 33 deletions

File tree

dojo/tools/pingcastle/parser.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,21 @@ def get_label_for_scan_types(self, scan_type):
2121
def get_description_for_scan_types(self, scan_type):
2222
return "PingCastle XML export"
2323

24-
# --- public API ---
25-
2624
def get_findings(self, file, test):
2725
tree = parse(file)
2826
root = tree.getroot()
2927
dupes = {}
3028
report_date = self._parse_datetime(root.findtext("GenerationDate"))
3129
domain_fqdn = root.findtext("DomainFQDN") or ""
32-
# Collect DC info & endpoints for enrichment
3330
dc_infos, dc_endpoints = self._collect_domain_controllers(root)
34-
# Store (not in dupes; summary is standalone)
3531
findings = []
36-
37-
# 1) Risk rules -> findings
3832
for rr in root.findall("RiskRules/HealthcheckRiskRule"):
3933
points = self._safe_int(rr.findtext("Points"))
4034
category = rr.findtext("Category") or ""
4135
model = rr.findtext("Model") or ""
4236
risk_id = rr.findtext("RiskId") or ""
4337
rationale = rr.findtext("Rationale") or ""
44-
4538
severity = self._map_points_to_severity(points)
46-
4739
title = f"[PingCastle] {risk_id} ({category}/{model})"
4840
description = self._compose_risk_rule_description(
4941
domain_fqdn=domain_fqdn,
@@ -55,7 +47,6 @@ def get_findings(self, file, test):
5547
dc_infos=dc_infos,
5648
root=root,
5749
)
58-
5950
finding = Finding(
6051
title=title,
6152
test=test,
@@ -67,40 +58,27 @@ def get_findings(self, file, test):
6758
)
6859
if report_date:
6960
finding.date = report_date
70-
71-
# CVE detection inside rationale (rare but helpful)
7261
cves = list(self.CVE_REGEX.findall(rationale or ""))
7362
if cves:
7463
finding.unsaved_vulnerability_ids = cves
75-
76-
# Attach endpoints: DC-specific risks get DC endpoints; others get domain endpoint
7764
finding.unsaved_endpoints = []
7865
if self._is_dc_specific_risk(risk_id):
7966
finding.unsaved_endpoints.extend(dc_endpoints)
8067
elif domain_fqdn:
8168
finding.unsaved_endpoints.append(Endpoint(host=domain_fqdn))
82-
83-
# Special enrichment for A-DC-Coerce: include RPC interfaces details if present
8469
if risk_id == "A-DC-Coerce":
8570
self._enrich_coerce_with_rpc_interfaces(finding, dc_infos)
86-
87-
# Special enrichment for A-DC-Spooler: reflect RemoteSpoolerDetected
8871
if risk_id == "A-DC-Spooler":
8972
self._enrich_spooler_status(finding, dc_infos)
90-
91-
# Special enrichment for password length (A-MinPwdLen): add current GPO settings if present
9273
if risk_id == "A-MinPwdLen":
9374
self._enrich_password_policy(finding, root)
94-
95-
# De-duplicate by risk_id
9675
dupe_key = risk_id
9776
if dupe_key in dupes:
9877
existing = dupes[dupe_key]
9978
existing.description += "\n\n-----\n\n" + finding.description
10079
existing.unsaved_endpoints.extend(finding.unsaved_endpoints)
10180
else:
10281
dupes[dupe_key] = finding
103-
10482
findings.extend(list(dupes.values()))
10583
return findings
10684

@@ -125,10 +103,7 @@ def _compose_risk_rule_description(
125103
lines.append(f"**Points**: `{points}`")
126104
if rationale:
127105
lines.append(f"**Rationale**: {rationale}")
128-
129-
# Context snippets, depending on category/model/risk_id
130106
if risk_id.startswith("A-DC-") or "DomainControllers" in root.tag:
131-
# Attach short DC summary table
132107
if dc_infos:
133108
lines.append("\n#### Domain Controllers")
134109
for dc in dc_infos:
@@ -149,15 +124,13 @@ def _collect_domain_controllers(self, root):
149124
remote_spooler = dc.findtext("RemoteSpoolerDetected") or "false"
150125
ip_elems = dc.findall("IP/string")
151126
ips = [ip_elem.text for ip_elem in ip_elems if ip_elem is not None and ip_elem.text]
152-
153127
dc_info = {
154128
"name": name,
155129
"os": os,
156130
"remote_spooler": remote_spooler.lower() == "true",
157131
"ips": ips,
158132
"rpc_interfaces": [],
159133
}
160-
161134
# RPC interfaces
162135
for rpc in dc.findall("RPCInterfacesOpen/HealthcheckDCRPCInterface"):
163136
dc_info["rpc_interfaces"].append({
@@ -166,9 +139,7 @@ def _collect_domain_controllers(self, root):
166139
"opnum": rpc.attrib.get("OpNum", ""),
167140
"function": rpc.attrib.get("Function", ""),
168141
})
169-
170142
dc_infos.append(dc_info)
171-
172143
# Endpoints: DC name + IPs
173144
if name:
174145
endpoints.append(Endpoint(host=name))
@@ -264,12 +235,10 @@ def _is_dc_specific_risk(risk_id: str, model: str = "", rationale: str = "") ->
264235
rid = (risk_id or "").strip()
265236
mod = (model or "").strip()
266237
rat = (rationale or "").strip().lower()
267-
268238
# 1) Explicit prefixes commonly used by PingCastle for DC-specific checks
269239
dc_prefixes = ("A-DC-", "S-DC-")
270240
if rid.startswith(dc_prefixes):
271241
return True
272-
273242
# 2) Known DC-specific RiskIds (extend as needed)
274243
dc_specific_ids = {
275244
"A-DC-Spooler",
@@ -279,11 +248,9 @@ def _is_dc_specific_risk(risk_id: str, model: str = "", rationale: str = "") ->
279248
}
280249
if rid in dc_specific_ids:
281250
return True
282-
283251
# 3) Model hints: "Audit" with a DC-focused RiskId, or PassTheCredential but DC scoped
284252
if mod == "Audit" and rid.endswith("DC"):
285253
return True
286-
287254
# 4) Rationale heuristic: mentions DC presence/quantity
288255
# examples: "remotely accessible from 1 DC", "on domain controllers", "DCs"
289256
dc_markers = (

0 commit comments

Comments
 (0)