Skip to content

Commit bbffa44

Browse files
committed
feat: add analytics and detection strategies to excel outputs
1 parent 39657a0 commit bbffa44

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

mitreattack/attackToExcel/attackToExcel.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ def build_dataframes(src: MemoryStore, domain: str) -> Dict:
108108
"matrices": stixToDf.matricesToDf(src, domain),
109109
"relationships": stixToDf.relationshipsToDf(src),
110110
"datasources": stixToDf.datasourcesToDf(src),
111+
"analytics": stixToDf.analyticsToDf(src),
112+
"detectionstrategies": stixToDf.detectionstrategiesToDf(src),
111113
}
112114
return df
113115

mitreattack/attackToExcel/stixToDf.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,66 @@ def datasourcesToDf(src):
333333
return dataframes
334334

335335

336+
def analyticsToDf(src):
337+
"""Parse STIX Analytics from the given data and return corresponding pandas dataframes.
338+
339+
:param src: MemoryStore or other stix2 DataSource object holding the domain data
340+
:returns: a lookup of labels (descriptors/names) to dataframes
341+
"""
342+
analytics = src.query([Filter("type", "=", "x-mitre-analytic")])
343+
analytics = remove_revoked_deprecated(analytics)
344+
345+
analytic_rows = []
346+
for analytic in tqdm(analytics, desc="parsing analytics"):
347+
analytic_rows.append(parseBaseStix(analytic))
348+
349+
citations = get_citations(analytics)
350+
dataframes = {
351+
"analytics": pd.DataFrame(analytic_rows).sort_values("name"),
352+
}
353+
if not citations.empty:
354+
dataframes["citations"] = citations.sort_values("reference")
355+
356+
return dataframes
357+
358+
359+
def detectionstrategiesToDf(src):
360+
"""Parse STIX Detection Strategies from the given data and return corresponding pandas dataframes.
361+
362+
:param src: MemoryStore or other stix2 DataSource object holding the domain data
363+
:returns: a lookup of labels (descriptors/names) to dataframes
364+
"""
365+
detection_strategies = src.query([Filter("type", "=", "x-mitre-detection-strategy")])
366+
detection_strategies = remove_revoked_deprecated(detection_strategies)
367+
368+
detection_strategy_rows = []
369+
for detection_strategy in tqdm(detection_strategies, desc="parsing detection strategies"):
370+
detection_strategy_rows.append(parseBaseStix(detection_strategy))
371+
372+
citations = get_citations(detection_strategies)
373+
dataframes = {
374+
"detectionstrategies": pd.DataFrame(detection_strategy_rows).sort_values("name"),
375+
}
376+
377+
# add relationships
378+
codex = relationshipsToDf(src, relatedType="detectionstrategy")
379+
dataframes.update(codex)
380+
# add relationship references
381+
dataframes["detectionstrategies"]["relationship citations"] = _get_relationship_citations(
382+
dataframes["detectionstrategies"], codex
383+
)
384+
# add/merge citations
385+
if not citations.empty:
386+
if "citations" in dataframes: # append to existing citations from references
387+
dataframes["citations"] = pd.concat([dataframes["citations"], citations])
388+
else: # add citations
389+
dataframes["citations"] = citations
390+
391+
dataframes["citations"].sort_values("reference")
392+
393+
return dataframes
394+
395+
336396
def softwareToDf(src):
337397
"""Parse STIX software from the given data and return corresponding pandas dataframes.
338398
@@ -893,6 +953,7 @@ def relationshipsToDf(src, relatedType=None):
893953
"mitigation": ["course-of-action"],
894954
"matrix": ["x-mitre-matrix"],
895955
"datasource": ["x-mitre-data-component"],
956+
"detectionstrategy": ["x-mitre-detection-strategy"],
896957
}
897958
stixToAttackTerm = {
898959
"attack-pattern": "technique",
@@ -906,6 +967,7 @@ def relationshipsToDf(src, relatedType=None):
906967
"x-mitre-data-source": "datasource",
907968
"campaign": "campaign",
908969
"x-mitre-asset": "asset",
970+
"x-mitre-detection-strategy": "detectionstrategy",
909971
}
910972

911973
mitre_attack_data = MitreAttackData(src=src)
@@ -1022,6 +1084,7 @@ def relationshipsToDf(src, relatedType=None):
10221084
attributedCampaignGroup = relationships.query("`mapping type` == 'attributed-to' and `target type` == 'group'")
10231085
relatedMitigations = relationships.query("`mapping type` == 'mitigates'")
10241086
targetedAssets = relationships.query("`mapping type` == 'targets' and `target type` == 'asset'")
1087+
detectedTechniques = relationships.query("`mapping type` == 'detects' and `source type` == 'detectionstrategy'")
10251088

10261089
if not relatedGroupSoftware.empty:
10271090
if relatedType == "group":
@@ -1067,6 +1130,13 @@ def relationshipsToDf(src, relatedType=None):
10671130
sheet_name = "associated techniques"
10681131
dataframes[sheet_name] = targetedAssets
10691132

1133+
if not detectedTechniques.empty:
1134+
if relatedType == "detectionstrategy":
1135+
sheet_name = "techniques detected"
1136+
else:
1137+
sheet_name = "associated detection strategies"
1138+
dataframes[sheet_name] = detectedTechniques
1139+
10701140
if not citations.empty:
10711141
# filter citations by ones actually used
10721142
# build master list of used citations

0 commit comments

Comments
 (0)