Skip to content

Commit 440283b

Browse files
committed
feat: add attack spec version 3.3.0 objects to stix20/ code
1 parent aaa5874 commit 440283b

2 files changed

Lines changed: 231 additions & 0 deletions

File tree

mitreattack/stix20/MitreAttackData.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@
2626
from stix2.utils import get_type_from_id
2727

2828
from mitreattack.stix20.custom_attack_objects import (
29+
Analytic,
2930
Asset,
3031
CustomStixObject,
3132
DataComponent,
3233
DataSource,
34+
DetectionStrategy,
3335
Matrix,
3436
StixObjectFactory,
3537
Tactic,
@@ -106,6 +108,8 @@ class MitreAttackData:
106108
"x-mitre-data-source",
107109
"x-mitre-data-component",
108110
"x-mitre-asset",
111+
"x-mitre-analytic",
112+
"x-mitre-detection-strategy",
109113
]
110114

111115
# --- Software/Group Relationships ---
@@ -148,6 +152,10 @@ class MitreAttackData:
148152
all_techniques_targeting_all_assets: Optional[RelationshipMapT[Technique]] = None
149153
all_assets_targeted_by_all_techniques: Optional[RelationshipMapT[Asset]] = None
150154

155+
# --- Detection Strategy/Technique Relationships ---
156+
all_detection_strategies_detecting_all_techniques: Optional[RelationshipMapT[DetectionStrategy]] = None
157+
all_techniques_detected_by_all_detection_strategies: Optional[RelationshipMapT[Technique]] = None
158+
151159
def __init__(self, stix_filepath: str | None = None, src: stix2.MemoryStore | None = None):
152160
"""Initialize a MitreAttackData object.
153161
@@ -431,6 +439,36 @@ def get_datacomponents(self, remove_revoked_deprecated: bool = False) -> list[Da
431439
"""
432440
return self.get_objects_by_type("x-mitre-data-component", remove_revoked_deprecated)
433441

442+
def get_analytics(self, remove_revoked_deprecated: bool = False) -> list[Analytic]:
443+
"""Retrieve all analytic objects.
444+
445+
Parameters
446+
----------
447+
remove_revoked_deprecated : bool, optional
448+
Remove revoked or deprecated objects from the query, by default False.
449+
450+
Returns
451+
-------
452+
list[Analytic]
453+
A list of Analytic objects.
454+
"""
455+
return self.get_objects_by_type("x-mitre-analytic", remove_revoked_deprecated)
456+
457+
def get_detectionstrategies(self, remove_revoked_deprecated: bool = False) -> list[DetectionStrategy]:
458+
"""Retrieve all detection strategy objects.
459+
460+
Parameters
461+
----------
462+
remove_revoked_deprecated : bool, optional
463+
Remove revoked or deprecated objects from the query, by default False.
464+
465+
Returns
466+
-------
467+
list[DetectionStrategy]
468+
A list of DetectionStrategy objects.
469+
"""
470+
return self.get_objects_by_type("x-mitre-detection-strategy", remove_revoked_deprecated)
471+
434472
###################################
435473
# Get STIX Objects by Value
436474
###################################
@@ -733,6 +771,37 @@ def get_techniques_used_by_group_software(self, group_stix_id: str) -> list[Tech
733771
technique_ids = [r.target_ref for r in software_uses]
734772
return self.src.query([Filter("type", "=", "attack-pattern"), Filter("id", "in", technique_ids)])
735773

774+
def get_analytics_by_detection_strategy(
775+
self, detection_strategy_stix_id: str, remove_revoked_deprecated: bool = False
776+
) -> list[Analytic]:
777+
"""Retrieve analytics for a detection strategy.
778+
779+
Parameters
780+
----------
781+
detection_strategy_stix_id: str
782+
Detection Strategy to search.
783+
remove_revoked_deprecated : bool, optional
784+
Remove revoked or deprecated objects from the query, by default False.
785+
786+
Returns
787+
-------
788+
list[Analytic]
789+
A list of Analytic objects referenced by the given detection strategy.
790+
791+
Raises
792+
------
793+
ValueError
794+
If no detection strategy with the given STIX ID is found.
795+
"""
796+
detection_strategy = self.get_object_by_stix_id(detection_strategy_stix_id)
797+
analytic_refs = self.get_field(detection_strategy, "x_mitre_analytic_refs", [])
798+
799+
filters = [Filter("type", "=", "x-mitre-analytic"), Filter("id", "in", analytic_refs)]
800+
analytics = self.src.query(filters)
801+
if remove_revoked_deprecated:
802+
analytics = self.remove_revoked_deprecated(analytics)
803+
return analytics
804+
736805
###################################
737806
# Get STIX Object by Value
738807
###################################
@@ -1960,3 +2029,87 @@ def get_assets_targeted_by_technique(self, technique_stix_id: str) -> list[Relat
19602029
if technique_stix_id in assets_targeted_by_techniques
19612030
else []
19622031
)
2032+
2033+
############################################
2034+
# Detection Strategy/Technique Relationships
2035+
############################################
2036+
2037+
def get_all_detection_strategies_detecting_all_techniques(self) -> RelationshipMapT[DetectionStrategy]:
2038+
"""Get all detection strategies detecting all techniques.
2039+
2040+
Returns
2041+
-------
2042+
RelationshipMapT[DetectionStrategy]
2043+
Mapping of asset_stix_id to RelationshipEntry[DetectionStrategy] for each detection strategy detecting the technique.
2044+
"""
2045+
# return data if it has already been fetched
2046+
if self.all_detection_strategies_detecting_all_techniques:
2047+
return self.all_detection_strategies_detecting_all_techniques
2048+
2049+
self.all_detection_strategies_detecting_all_techniques = self.get_related(
2050+
"x-mitre-detection-strategy", "detects", "attack-pattern", reverse=True
2051+
)
2052+
2053+
return self.all_detection_strategies_detecting_all_techniques
2054+
2055+
def get_detection_strategies_detecting_technique(
2056+
self, technique_stix_id: str
2057+
) -> list[RelationshipEntry[DetectionStrategy]]:
2058+
"""Get all detection strategies detecting a technique.
2059+
2060+
Parameters
2061+
----------
2062+
technique_stix_id : str
2063+
The STIX ID of the technique.
2064+
2065+
Returns
2066+
-------
2067+
list[RelationshipEntry[DetectionStrategy]]
2068+
List of RelationshipEntry[DetectionStrategy] for each detection strategy detecting the technique.
2069+
"""
2070+
detection_strategies_detecting_techniques = self.get_all_detection_strategies_detecting_all_techniques()
2071+
return (
2072+
detection_strategies_detecting_techniques[technique_stix_id]
2073+
if technique_stix_id in detection_strategies_detecting_techniques
2074+
else []
2075+
)
2076+
2077+
def get_all_techniques_detected_by_all_detection_strategies(self) -> RelationshipMapT[Technique]:
2078+
"""Get all techniques detected by all detection strategies.
2079+
2080+
Returns
2081+
-------
2082+
RelationshipMapT[Technique]
2083+
Mapping of detection_strategy_stix_id to RelationshipEntry[Technique] for each technique detected by the detection strategy.
2084+
"""
2085+
# return data if it has already been fetched
2086+
if self.all_techniques_detected_by_all_detection_strategies:
2087+
return self.all_techniques_detected_by_all_detection_strategies
2088+
2089+
self.all_techniques_detected_by_all_detection_strategies = self.get_related(
2090+
"x-mitre-detection-strategy", "detects", "attack-pattern"
2091+
)
2092+
2093+
return self.all_techniques_detected_by_all_detection_strategies
2094+
2095+
def get_techniques_detected_by_detection_strategy(
2096+
self, detection_strategy_stix_id: str
2097+
) -> list[RelationshipEntry[Technique]]:
2098+
"""Get all techniques detected by a detection strategy.
2099+
2100+
Parameters
2101+
----------
2102+
detection_strategy_stix_id : str
2103+
The STIX ID of the detection strategy.
2104+
2105+
Returns
2106+
-------
2107+
list[RelationshipEntry[Technique]]
2108+
List of RelationshipEntry[Technique] for each technique detected by the detection strategy.
2109+
"""
2110+
techniques_detected_by_detection_strategies = self.get_all_techniques_detected_by_all_detection_strategies()
2111+
return (
2112+
techniques_detected_by_detection_strategies[detection_strategy_stix_id]
2113+
if detection_strategy_stix_id in techniques_detected_by_detection_strategies
2114+
else []
2115+
)

mitreattack/stix20/custom_attack_objects.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def StixObjectFactory(data: dict) -> Union[CustomStixObject, stix2.v20.sdo._Doma
8080
"x-mitre-data-source": DataSource,
8181
"x-mitre-data-component": DataComponent,
8282
"x-mitre-asset": Asset,
83+
"x-mitre-analytic": Analytic,
84+
"x-mitre-detection-strategy": DetectionStrategy,
8385
}
8486

8587
stix_type = data.get("type")
@@ -220,6 +222,7 @@ class DataSource(CustomStixObject, object):
220222
("x_mitre_attack_spec_version", StringProperty()),
221223
# Data Component Properties
222224
("x_mitre_data_source_ref", ReferenceProperty(valid_types="x-mitre-data-source", spec_version="2.0")),
225+
("x_mitre_log_sources", ListProperty(DictionaryProperty())),
223226
],
224227
)
225228
class DataComponent(CustomStixObject, object):
@@ -228,6 +231,7 @@ class DataComponent(CustomStixObject, object):
228231
Custom Properties
229232
-----------------
230233
x_mitre_data_source_ref: str
234+
x_mitre_log_sources: list[object]
231235
"""
232236

233237
pass
@@ -268,3 +272,77 @@ class Asset(CustomStixObject, object):
268272
"""
269273

270274
pass
275+
276+
277+
@CustomObject(
278+
"x-mitre-analytic",
279+
[
280+
# SDO Common Properties
281+
("id", IDProperty("x-mitre-analytic", spec_version="2.0")),
282+
("type", TypeProperty("x-mitre-analytic", spec_version="2.0")),
283+
("created_by_ref", ReferenceProperty(valid_types="identity", spec_version="2.0")),
284+
("created", TimestampProperty(precision="millisecond")),
285+
("modified", TimestampProperty(precision="millisecond")),
286+
("revoked", BooleanProperty(default=lambda: False)),
287+
("external_references", ListProperty(ExternalReference)),
288+
("object_marking_refs", ListProperty(ReferenceProperty(valid_types="marking-definition", spec_version="2.0"))),
289+
("name", StringProperty(required=True)),
290+
("description", StringProperty()),
291+
("x_mitre_modified_by_ref", ReferenceProperty(valid_types="identity", spec_version="2.0")),
292+
("x_mitre_version", StringProperty()),
293+
("x_mitre_attack_spec_version", StringProperty()),
294+
("x_mitre_domains", ListProperty(StringProperty())),
295+
("x_mitre_contributors", ListProperty(StringProperty())),
296+
("x-mitre-deprecated", BooleanProperty(default=lambda: False)),
297+
# Analytic Properties
298+
("x_mitre_platforms", ListProperty(StringProperty())),
299+
("x_mitre_log_source_references", ListProperty(DictionaryProperty())),
300+
("x_mitre_mutable_elements", ListProperty(DictionaryProperty())),
301+
],
302+
)
303+
class Analytic(CustomStixObject, object):
304+
"""Custom Analytic object of type stix2.CustomObject.
305+
306+
Custom Properties
307+
-----------------
308+
x_mitre_platforms: list[str]
309+
x_mitre_log_source_references: list[object]
310+
x_mitre_mutable_elements: list[object]
311+
"""
312+
313+
pass
314+
315+
316+
@CustomObject(
317+
"x-mitre-detection-strategy",
318+
[
319+
# SDO Common Properties
320+
("id", IDProperty("x-mitre-detection-strategy", spec_version="2.0")),
321+
("type", TypeProperty("x-mitre-detection-strategy", spec_version="2.0")),
322+
("created_by_ref", ReferenceProperty(valid_types="identity", spec_version="2.0")),
323+
("created", TimestampProperty(precision="millisecond")),
324+
("modified", TimestampProperty(precision="millisecond")),
325+
("revoked", BooleanProperty(default=lambda: False)),
326+
("external_references", ListProperty(ExternalReference)),
327+
("object_marking_refs", ListProperty(ReferenceProperty(valid_types="marking-definition", spec_version="2.0"))),
328+
("name", StringProperty(required=True)),
329+
("description", StringProperty()),
330+
("x_mitre_modified_by_ref", ReferenceProperty(valid_types="identity", spec_version="2.0")),
331+
("x_mitre_version", StringProperty()),
332+
("x_mitre_attack_spec_version", StringProperty()),
333+
("x_mitre_domains", ListProperty(StringProperty())),
334+
("x_mitre_contributors", ListProperty(StringProperty())),
335+
("x-mitre-deprecated", BooleanProperty(default=lambda: False)),
336+
# Detection Strategy Properties
337+
("x_mitre_analytic_refs", ListProperty(StringProperty())),
338+
],
339+
)
340+
class DetectionStrategy(CustomStixObject, object):
341+
"""Custom Detection Strategy object of type stix2.CustomObject.
342+
343+
Custom Properties
344+
-----------------
345+
x_mitre_analytic_refs: list[str]
346+
"""
347+
348+
pass

0 commit comments

Comments
 (0)