@@ -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+
336396def 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