Skip to content

Commit ec53016

Browse files
committed
fix: add support for detection strategy>technique detection relationships in changelog_helper
1 parent 6db4a92 commit ec53016

1 file changed

Lines changed: 83 additions & 33 deletions

File tree

mitreattack/diffStix/changelog_helper.py

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def __init__(
108108
self.new = new
109109
self.show_key = show_key
110110
self.site_prefix = site_prefix
111-
self.types = ["techniques", "software", "groups", "campaigns", "assets", "mitigations", "datasources", "datacomponents"]
111+
self.types = ["techniques", "software", "groups", "campaigns", "assets", "mitigations", "datasources", "datacomponents", "detectionstrategies", "analytics", "logsources"]
112112
self.use_mitre_cti = use_mitre_cti
113113
self.verbose = verbose
114114
self.include_contributors = include_contributors
@@ -127,6 +127,9 @@ def __init__(
127127
"mitigations": "Mitigations",
128128
"datasources": "Data Sources",
129129
"datacomponents": "Data Components",
130+
"detectionstrategies": "Detection Strategies",
131+
"analytics": "Analytics",
132+
"logsources": "Log Sources",
130133
}
131134

132135
self.section_descriptions = {
@@ -462,45 +465,74 @@ def find_technique_detection_changes(self, new_stix_obj: dict, domain: str):
462465
stix_id = new_stix_obj["id"]
463466
all_old_domain_datasources = self.data["old"][domain]["attack_objects"]["datasources"]
464467
all_old_domain_datacomponents = self.data["old"][domain]["attack_objects"]["datacomponents"]
468+
all_old_domain_detectionstrategies = self.data["old"][domain]["attack_objects"]["detectionstrategies"]
465469
all_new_domain_datasources = self.data["new"][domain]["attack_objects"]["datasources"]
466470
all_new_domain_datacomponents = self.data["new"][domain]["attack_objects"]["datacomponents"]
467-
old_detections = {}
468-
new_detections = {}
471+
all_new_domain_detectionstrategies = self.data["new"][domain]["attack_objects"]["detectionstrategies"]
472+
473+
old_datacomponent_detections = {}
474+
old_detectionstrategy_detections = {}
475+
new_datacomponent_detections = {}
476+
new_detectionstrategy_detections = {}
469477

470478
for _, detection_relationship in self.data["old"][domain]["relationships"]["detections"].items():
471479
if detection_relationship.get("x_mitre_deprecated") or detection_relationship.get("revoked"):
472480
continue
473481
if stix_id == detection_relationship["target_ref"]:
474-
old_datacomponent_id = detection_relationship["source_ref"]
475-
old_datacomponent = all_old_domain_datacomponents[old_datacomponent_id]
476-
old_datasource_id = old_datacomponent["x_mitre_data_source_ref"]
477-
old_datasource = all_old_domain_datasources[old_datasource_id]
478-
old_datasource_attack_id = get_attack_id(stix_obj=old_datasource)
479-
old_detections[
480-
old_datacomponent_id
481-
] = f"{old_datasource_attack_id}: {old_datasource['name']} ({old_datacomponent['name']})"
482+
old_sourceref_id = detection_relationship["source_ref"]
483+
if old_sourceref_id in all_old_domain_datacomponents:
484+
old_datacomponent = all_old_domain_datacomponents[old_sourceref_id]
485+
old_datasource_id = old_datacomponent["x_mitre_data_source_ref"]
486+
old_datasource = all_old_domain_datasources[old_datasource_id]
487+
old_datasource_attack_id = get_attack_id(stix_obj=old_datasource)
488+
old_datacomponent_detections[
489+
old_sourceref_id
490+
] = f"{old_datasource_attack_id}: {old_datasource['name']} ({old_datacomponent['name']})"
491+
if old_sourceref_id in all_old_domain_detectionstrategies:
492+
old_detectionstrategy = all_old_domain_detectionstrategies[old_sourceref_id]
493+
old_detectionstrategy_attack_id = get_attack_id(stix_obj=old_detectionstrategy)
494+
old_detectionstrategy_detections[
495+
old_sourceref_id
496+
] = f"{old_detectionstrategy_attack_id}: {old_detectionstrategy['name']}"
482497

483498
for _, detection_relationship in self.data["new"][domain]["relationships"]["detections"].items():
484499
if detection_relationship.get("x_mitre_deprecated") or detection_relationship.get("revoked"):
485500
continue
486501
if stix_id == detection_relationship["target_ref"]:
487-
new_datacomponent_id = detection_relationship["source_ref"]
488-
new_datacomponent = all_new_domain_datacomponents[new_datacomponent_id]
489-
new_datasource_id = new_datacomponent["x_mitre_data_source_ref"]
490-
new_datasource = all_new_domain_datasources[new_datasource_id]
491-
new_datasource_attack_id = get_attack_id(stix_obj=new_datasource)
492-
new_detections[
493-
new_datacomponent_id
494-
] = f"{new_datasource_attack_id}: {new_datasource['name']} ({new_datacomponent['name']})"
495-
496-
shared_detections = old_detections.keys() & new_detections.keys()
497-
brand_new_detections = new_detections.keys() - old_detections.keys()
498-
dropped_detections = old_detections.keys() - new_detections.keys()
499-
500-
new_stix_obj["changelog_detections"] = {
501-
"shared": sorted([f"{new_detections[stix_id]}" for stix_id in shared_detections]),
502-
"new": sorted([f"{new_detections[stix_id]}" for stix_id in brand_new_detections]),
503-
"dropped": sorted([f"{old_detections[stix_id]}" for stix_id in dropped_detections]),
502+
new_sourceref_id = detection_relationship["source_ref"]
503+
if new_sourceref_id in all_new_domain_datacomponents:
504+
new_datacomponent = all_new_domain_datacomponents[new_sourceref_id]
505+
new_datasource_id = new_datacomponent["x_mitre_data_source_ref"]
506+
new_datasource = all_new_domain_datasources[new_datasource_id]
507+
new_datasource_attack_id = get_attack_id(stix_obj=new_datasource)
508+
new_datacomponent_detections[
509+
new_sourceref_id
510+
] = f"{new_datasource_attack_id}: {new_datasource['name']} ({new_datacomponent['name']})"
511+
if new_sourceref_id in all_new_domain_detectionstrategies:
512+
new_detectionstrategy = all_new_domain_detectionstrategies[new_sourceref_id]
513+
new_detectionstrategy_attack_id = get_attack_id(stix_obj=new_detectionstrategy)
514+
new_detectionstrategy_detections[
515+
new_sourceref_id
516+
] = f"{new_detectionstrategy_attack_id}: {new_detectionstrategy['name']}"
517+
518+
shared_datacomponent_detections = old_datacomponent_detections.keys() & new_datacomponent_detections.keys()
519+
brand_new_datacomponent_detections = new_datacomponent_detections.keys() - old_datacomponent_detections.keys()
520+
dropped_datacomponent_detections = old_datacomponent_detections.keys() - new_datacomponent_detections.keys()
521+
522+
new_stix_obj["changelog_datacomponent_detections"] = {
523+
"shared": sorted([f"{new_datacomponent_detections[stix_id]}" for stix_id in shared_datacomponent_detections]),
524+
"new": sorted([f"{new_datacomponent_detections[stix_id]}" for stix_id in brand_new_datacomponent_detections]),
525+
"dropped": sorted([f"{old_datacomponent_detections[stix_id]}" for stix_id in dropped_datacomponent_detections]),
526+
}
527+
528+
shared_detectionstrategy_detections = old_detectionstrategy_detections.keys() & new_detectionstrategy_detections.keys()
529+
brand_new_detectionstrategy_detections = new_detectionstrategy_detections.keys() - old_detectionstrategy_detections.keys()
530+
dropped_detectionstrategy_detections = old_detectionstrategy_detections.keys() - new_detectionstrategy_detections.keys()
531+
532+
new_stix_obj["changelog_detectionstrategy_detections"] = {
533+
"shared": sorted([f"{new_detectionstrategy_detections[stix_id]}" for stix_id in shared_detectionstrategy_detections]),
534+
"new": sorted([f"{new_detectionstrategy_detections[stix_id]}" for stix_id in brand_new_detectionstrategy_detections]),
535+
"dropped": sorted([f"{old_detectionstrategy_detections[stix_id]}" for stix_id in dropped_detectionstrategy_detections]),
504536
}
505537

506538
def load_domain(self, domain: str):
@@ -589,6 +621,9 @@ def parse_extra_data(self, data_store: stix2.MemoryStore, domain: str, datastore
589621
"mitigations": [Filter("type", "=", "course-of-action")],
590622
"datasources": [Filter("type", "=", "x-mitre-data-source")],
591623
"datacomponents": [Filter("type", "=", "x-mitre-data-component")],
624+
"detectionstrategies": [Filter("type", "=", "x-mitre-detection-strategy")],
625+
"analytics": [Filter("type", "=", "x-mitre-analytic")],
626+
"logsources": [Filter("type", "=", "x-mitre-log-source")],
592627
}
593628
for object_type, stix_filters in attack_type_to_stix_filter.items():
594629
raw_data = []
@@ -1669,17 +1704,32 @@ def write_detailed_html(html_file_detailed: str, diffStix: DiffStix):
16691704
lines.append("</ul>")
16701705

16711706
# Detections!
1672-
if stix_object.get("changelog_detections"):
1673-
new_detections = stix_object["changelog_detections"].get("new")
1674-
dropped_detections = stix_object["changelog_detections"].get("dropped")
1707+
if stix_object.get("changelog_datacomponent_detections"):
1708+
new_detections = stix_object["changelog_datacomponent_detections"].get("new")
1709+
dropped_detections = stix_object["changelog_datacomponent_detections"].get("dropped")
1710+
if new_detections:
1711+
lines.append("<p><b>New Detections (Data Components -> Technique)</b>:</p>")
1712+
lines.append("<ul>")
1713+
for detection in new_detections:
1714+
lines.append(f" <li>{detection}</li>")
1715+
lines.append("</ul>")
1716+
if dropped_detections:
1717+
lines.append("<p><b>Dropped Detections (Data Components -> Technique)</b>:</p>")
1718+
lines.append("<ul>")
1719+
for detection in dropped_detections:
1720+
lines.append(f" <li>{detection}</li>")
1721+
lines.append("</ul>")
1722+
if stix_object.get("changelog_detectionstrategy_detections"):
1723+
new_detections = stix_object["changelog_detectionstrategy_detections"].get("new")
1724+
dropped_detections = stix_object["changelog_detectionstrategy_detections"].get("dropped")
16751725
if new_detections:
1676-
lines.append("<p><b>New Detections</b>:</p>")
1726+
lines.append("<p><b>New Detections (Detection Strategies -> Technique)</b>:</p>")
16771727
lines.append("<ul>")
16781728
for detection in new_detections:
16791729
lines.append(f" <li>{detection}</li>")
16801730
lines.append("</ul>")
16811731
if dropped_detections:
1682-
lines.append("<p><b>Dropped Detections</b>:</p>")
1732+
lines.append("<p><b>Dropped Detections (Detection Strategies -> Technique)</b>:</p>")
16831733
lines.append("<ul>")
16841734
for detection in dropped_detections:
16851735
lines.append(f" <li>{detection}</li>")

0 commit comments

Comments
 (0)