@@ -211,6 +211,20 @@ def translate_stix_objects(self, stix_objects):
211
211
"x_mitre_collection_layers" : "collection_layers" ,
212
212
"x_mitre_contributors" : "contributors"
213
213
}
214
+ campaign_stix_mapping = {
215
+ "type" : "type" ,
216
+ "id" : "id" ,
217
+ "created_by_ref" : "created_by_ref" ,
218
+ "created" : "created" ,
219
+ "modified" : "modified" ,
220
+ "name" : "name" ,
221
+ "description" : "campaign_description" ,
222
+ "aliases" : "campaign_aliases" ,
223
+ "object_marking_refs" : "object_marking_refs" ,
224
+ "external_references" : "external_references" ,
225
+ "x_mitre_first_seen_citation" : "first_seen_citation" ,
226
+ "x_mitre_last_seen_citation" : "last_seen_citation"
227
+ }
214
228
215
229
# ******** Helper Functions ********
216
230
def handle_list (list_object , object_type ):
@@ -233,6 +247,8 @@ def handle_list(list_object, object_type):
233
247
obj_dict ['tactic_id' ] = list_object [0 ]['external_id' ]
234
248
elif obj_dict ['type' ] == 'matrix' :
235
249
obj_dict ['matrix_id' ] = list_object [0 ]['external_id' ]
250
+ elif obj_dict ['type' ] == 'campaign' :
251
+ obj_dict ['campaign_id' ] = list_object [0 ]['external_id' ]
236
252
elif object_type == "kill_chain_phases" :
237
253
tactic_list = list ()
238
254
for phase in list_object :
@@ -269,6 +285,8 @@ def handle_list(list_object, object_type):
269
285
stix_mapping = marking_stix_mapping
270
286
elif obj ['type' ] == "x-mitre-data-source" :
271
287
stix_mapping = data_source_stix_mapping
288
+ elif obj ['type' ] == "campaign" :
289
+ stix_mapping = campaign_stix_mapping
272
290
else :
273
291
return stix_objects_list
274
292
@@ -333,7 +351,8 @@ def get_enterprise(self, stix_format=True):
333
351
"tactics" : self .get_enterprise_tactics ,
334
352
"matrix" : Filter ("type" , "=" , "x-mitre-matrix" ),
335
353
"identity" : Filter ("type" , "=" , "identity" ),
336
- "marking-definition" : Filter ("type" , "=" , "marking-definition" )
354
+ "marking-definition" : Filter ("type" , "=" , "marking-definition" ),
355
+ "campaign" : self .get_enterprise_campaigns
337
356
}
338
357
enterprise_stix_objects = dict ()
339
358
for key in enterprise_filter_objects :
@@ -342,6 +361,25 @@ def get_enterprise(self, stix_format=True):
342
361
enterprise_stix_objects [key ] = self .translate_stix_objects (enterprise_stix_objects [key ])
343
362
return enterprise_stix_objects
344
363
364
+ def get_enterprise_campaigns (self , skip_revoked_deprecated = True , stix_format = True ):
365
+ """ Extracts all the available campaigns STIX objects in the Enterprise ATT&CK matrix
366
+
367
+ Args:
368
+ skip_revoked_deprecated (bool): default True. Skip revoked and deprecated STIX objects.
369
+ stix_format (bool): Returns results in original STIX format or friendly syntax (e.g. 'attack-pattern' or 'technique')
370
+
371
+ Returns:
372
+ List of STIX objects
373
+ """
374
+ enterprise_campaigns = self .TC_ENTERPRISE_SOURCE .query ([Filter ("type" , "=" , "campaign" )])
375
+
376
+ if skip_revoked_deprecated :
377
+ enterprise_campaigns = self .remove_revoked_deprecated (enterprise_campaigns )
378
+
379
+ if not stix_format :
380
+ enterprise_campaigns = self .translate_stix_objects (enterprise_campaigns )
381
+ return enterprise_campaigns
382
+
345
383
def get_enterprise_techniques (self , skip_revoked_deprecated = True , include_subtechniques = True , enrich_data_sources = False , stix_format = True ):
346
384
""" Extracts all the available techniques STIX objects in the Enterprise ATT&CK matrix
347
385
@@ -639,15 +677,36 @@ def get_mobile(self, stix_format=True):
639
677
"tactics" : self .get_mobile_tactics ,
640
678
"matrix" : Filter ("type" , "=" , "x-mitre-matrix" ),
641
679
"identity" : Filter ("type" , "=" , "identity" ),
642
- "marking-definition" : Filter ("type" , "=" , "marking-definition" )
680
+ "marking-definition" : Filter ("type" , "=" , "marking-definition" ),
681
+ "campaigns" : self .get_mobile_campaigns
643
682
}
644
683
mobile_stix_objects = {}
645
684
for key in mobile_filter_objects :
646
685
mobile_stix_objects [key ] = self .TC_MOBILE_SOURCE .query (mobile_filter_objects [key ]) if isinstance (mobile_filter_objects [key ], Filter ) else mobile_filter_objects [key ]()
647
686
if not stix_format :
648
687
mobile_stix_objects [key ] = self .translate_stix_objects (mobile_stix_objects [key ])
649
688
return mobile_stix_objects
650
-
689
+
690
+ def get_mobile_campaigns (self , skip_revoked_deprecated = True , stix_format = True ):
691
+ """ Extracts all the available techniques STIX objects in the Mobile ATT&CK matrix
692
+
693
+ Args:
694
+ skip_revoked_deprecated (bool): default True. Skip revoked and deprecated STIX objects.
695
+ stix_format (bool): Returns results in original STIX format or friendly syntax (e.g. 'attack-pattern' or 'technique')
696
+
697
+ Returns:
698
+ List of STIX objects
699
+ """
700
+
701
+ mobile_campaigns = self .TC_MOBILE_SOURCE .query (Filter ("type" , "=" , "campaign" ))
702
+
703
+ if skip_revoked_deprecated :
704
+ mobile_campaigns = self .remove_revoked_deprecated (mobile_campaigns )
705
+
706
+ if not stix_format :
707
+ mobile_campaigns = self .translate_stix_objects (mobile_campaigns )
708
+ return mobile_campaigns
709
+
651
710
def get_mobile_techniques (self , skip_revoked_deprecated = True , include_subtechniques = True , stix_format = True ):
652
711
""" Extracts all the available techniques STIX objects in the Mobile ATT&CK matrix
653
712
@@ -948,7 +1007,32 @@ def get_stix_objects(self, stix_format=True):
948
1007
for resource_type in attack_stix_objects [matrix ].keys ():
949
1008
attack_stix_objects [matrix ][resource_type ] = self .translate_stix_objects (attack_stix_objects [matrix ][resource_type ])
950
1009
return attack_stix_objects
951
-
1010
+
1011
+ def get_campaigns (self , skip_revoked_deprecated = True , stix_format = True ):
1012
+ """ Extracts all the available campaigns STIX objects across all ATT&CK matrices
1013
+
1014
+ Args:
1015
+ skip_revoked_deprecated (bool): default True. Skip revoked and deprecated STIX objects.
1016
+ stix_format (bool): Returns results in original STIX format or friendly syntax (e.g. 'attack-pattern' or 'technique')
1017
+
1018
+ Returns:
1019
+ List of STIX objects
1020
+ """
1021
+
1022
+ enterprise_campaigns = self .get_enterprise_campaigns ()
1023
+ mobile_campaigns = self .get_mobile_campaigns ()
1024
+ for mc in mobile_campaigns :
1025
+ if mc not in enterprise_campaigns :
1026
+ enterprise_campaigns .append (mc )
1027
+
1028
+ if skip_revoked_deprecated :
1029
+ enterprise_campaigns = self .remove_revoked_deprecated (enterprise_campaigns )
1030
+
1031
+ if not stix_format :
1032
+ enterprise_campaigns = self .translate_stix_objects (enterprise_campaigns )
1033
+
1034
+ return enterprise_campaigns
1035
+
952
1036
def get_techniques (self , include_subtechniques = True , skip_revoked_deprecated = True , enrich_data_sources = False , stix_format = True ):
953
1037
""" Extracts all the available techniques STIX objects across all ATT&CK matrices
954
1038
@@ -1272,7 +1356,7 @@ def get_object_by_attack_id(self, object_type, attack_id, stix_format=True):
1272
1356
List of STIX objects
1273
1357
1274
1358
"""
1275
- valid_objects = {'attack-pattern' ,'course-of-action' ,'intrusion-set' ,'malware' ,'tool' ,'x-mitre-data-source' , 'x-mitre-data-component' }
1359
+ valid_objects = {'attack-pattern' ,'course-of-action' ,'intrusion-set' ,'malware' ,'tool' ,'x-mitre-data-source' , 'x-mitre-data-component' , 'campaign' }
1276
1360
if object_type not in valid_objects :
1277
1361
raise ValueError (f"ERROR: Valid object must be one of { valid_objects } " )
1278
1362
else :
@@ -1285,6 +1369,36 @@ def get_object_by_attack_id(self, object_type, attack_id, stix_format=True):
1285
1369
all_stix_objects = self .translate_stix_objects (all_stix_objects )
1286
1370
return all_stix_objects
1287
1371
1372
+ def get_campaign_by_alias (self , campaign_alias , case = True , stix_format = True ):
1373
+ """ Extracts campaign STIX objects by alias name accross all ATT&CK matrices
1374
+
1375
+ Args:
1376
+ campaign_alias (str) : Alias of threat actor group
1377
+ case (bool) : case sensitive or not
1378
+ stix_format (bool): Returns results in original STIX format or friendly syntax (e.g. 'attack-pattern' or 'technique')
1379
+
1380
+ Returns:
1381
+ List of STIX objects
1382
+
1383
+ """
1384
+ if not case :
1385
+ all_campaigns = self .get_campaigns ()
1386
+ all_campaigns_list = list ()
1387
+ for campaign in all_campaigns :
1388
+ if "aliases" in campaign .keys ():
1389
+ for alias in campaign ['aliases' ]:
1390
+ if campaign_alias .lower () in alias .lower ():
1391
+ all_campaigns_list .append (campaign )
1392
+ else :
1393
+ filter_objects = [
1394
+ Filter ('type' , '=' , 'campaign' ),
1395
+ Filter ('aliases' , '=' , campaign_alias )
1396
+ ]
1397
+ all_campaigns_list = self .COMPOSITE_DS .query (filter_objects )
1398
+ if not stix_format :
1399
+ all_campaigns_list = self .translate_stix_objects (all_campaigns_list )
1400
+ return all_campaigns_list
1401
+
1288
1402
def get_group_by_alias (self , group_alias , case = True , stix_format = True ):
1289
1403
""" Extracts group STIX objects by alias name accross all ATT&CK matrices
1290
1404
@@ -1314,7 +1428,27 @@ def get_group_by_alias(self, group_alias, case=True, stix_format=True):
1314
1428
if not stix_format :
1315
1429
all_groups_list = self .translate_stix_objects (all_groups_list )
1316
1430
return all_groups_list
1317
-
1431
+
1432
+ def get_campaigns_since_time (self , timestamp , stix_format = True ):
1433
+ """ Extracts campaings STIX objects since specific time accross all ATT&CK matrices
1434
+
1435
+ Args:
1436
+ timestamp (timestamp): Timestamp
1437
+ stix_format (bool): Returns results in original STIX format or friendly syntax (e.g. 'attack-pattern' or 'technique')
1438
+
1439
+ Returns:
1440
+ List of STIX objects
1441
+
1442
+ """
1443
+ filter_objects = [
1444
+ Filter ('type' , '=' , 'campaign' ),
1445
+ Filter ('created' , '>' , timestamp )
1446
+ ]
1447
+ all_campaigns_list = self .COMPOSITE_DS .query (filter_objects )
1448
+ if not stix_format :
1449
+ all_campaigns_list = self .translate_stix_objects (all_campaigns_list )
1450
+ return all_campaigns_list
1451
+
1318
1452
def get_techniques_since_time (self , timestamp , stix_format = True ):
1319
1453
""" Extracts techniques STIX objects since specific time accross all ATT&CK matrices
1320
1454
@@ -1807,4 +1941,4 @@ def enrich_techniques_data_sources(self, stix_object):
1807
1941
if technique_ds :
1808
1942
new_data_sources = [ v for v in technique_ds .values ()]
1809
1943
stix_object [i ] = stix_object [i ].new_version (x_mitre_data_sources = new_data_sources )
1810
- return stix_object
1944
+ return stix_object
0 commit comments