@@ -17,7 +17,7 @@ def __init__(self, opencti):
1717 self .opencti = opencti
1818 self .mapping_cache = {}
1919
20- def unknown_type (self , stix_object ):
20+ def unknown_type (self , stix_object , update = False ):
2121 self .opencti .log ('Unknown object type "' + stix_object ['type' ] + '", doing nothing...' )
2222
2323 def convert_markdown (self , text ):
@@ -311,8 +311,10 @@ def import_object(self, stix_object, update=False):
311311 else :
312312 published = datetime .datetime .today ().strftime ('%Y-%m-%dT%H:%M:%SZ' )
313313
314- if 'mitre-attack ( ' in source_name and 'name' in stix_object :
314+ if 'mitre' in source_name and 'name' in stix_object :
315315 title = '[MITRE ATT&CK] ' + stix_object ['name' ]
316+ if 'modified' in stix_object :
317+ published = stix_object ['modified' ]
316318 else :
317319 title = source_name
318320
@@ -392,7 +394,7 @@ def import_object(self, stix_object, update=False):
392394 'course-of-action' : self .create_course_of_action ,
393395 'report' : self .create_report ,
394396 }
395- do_import = importer .get (stix_object ['type' ], lambda stix_object : self .unknown_type (stix_object ))
397+ do_import = importer .get (stix_object ['type' ], lambda stix_object , update : self .unknown_type (stix_object , update ))
396398 stix_object_result = do_import (stix_object , update )
397399
398400 # Add embedded relationships
@@ -465,6 +467,8 @@ def export_identity(self, entity):
465467 'x_opencti_id' : entity ['id' ],
466468 'x_opencti_aliases' : entity ['alias' ],
467469 }
470+ if entity ['entity_type' ] == 'organization' and 'organization_class' in entity :
471+ identity ['x_opencti_organization_class' ] = entity ['organization_class' ]
468472 return self .prepare_export (entity , identity )
469473
470474 def create_identity (self , stix_object , update = False ):
@@ -667,7 +671,7 @@ def export_tool(self, entity):
667671 }
668672 return self .prepare_export (entity , tool )
669673
670- def create_tool (self , stix_object ):
674+ def create_tool (self , stix_object , update = False ):
671675 return self .opencti .create_tool_if_not_exists (
672676 stix_object ['name' ],
673677 self .convert_markdown (stix_object ['description' ]) if 'description' in stix_object else '' ,
@@ -735,7 +739,7 @@ def create_attack_pattern(self, stix_object, update=False):
735739 if 'x_mitre_platforms' in stix_object :
736740 self .opencti .update_stix_domain_entity_field (attack_pattern ['id' ], 'platform' , stix_object ['x_mitre_platforms' ])
737741 if 'x_mitre_permissions_required' in stix_object :
738- self .opencti .update_stix_domain_entity_field (attack_pattern ['id' ], 'required_permission' , stix_object ['x_mitre_permissions_required' ])
742+ self .opencti .update_stix_domain_entity_field (attack_pattern ['id' ], 'required_permission' , stix_object ['x_mitre_permissions_required' ])
739743 return attack_pattern
740744
741745 def export_course_of_action (self , entity ):
@@ -823,7 +827,7 @@ def export_stix_relation(self, entity):
823827 }
824828 return self .prepare_export (entity , stix_relation )
825829
826- def import_relationship (self , stix_relation ):
830+ def import_relationship (self , stix_relation , update = False ):
827831 # Check relation
828832 stix_relation_result = self .opencti .get_stix_relation_by_stix_id (stix_relation ['id' ])
829833 if stix_relation_result is not None :
@@ -854,6 +858,20 @@ def import_relationship(self, stix_relation):
854858 self .opencti .log ('Target ref of the relationship not found, doing nothing...' )
855859 return None
856860
861+ date = None
862+ if 'external_references' in stix_relation :
863+ for external_reference in stix_relation ['external_references' ]:
864+ if 'description' in external_reference :
865+ matches = list (datefinder .find_dates (external_reference ['description' ]))
866+ else :
867+ matches = list (datefinder .find_dates (external_reference ['source_name' ]))
868+ if len (matches ) > 0 :
869+ date = matches [0 ].strftime ('%Y-%m-%dT%H:%M:%SZ' )
870+ else :
871+ date = datetime .datetime .today ().strftime ('%Y-%m-%dT%H:%M:%SZ' )
872+ if date is None :
873+ date = datetime .datetime .utcnow ().replace (microsecond = 0 , tzinfo = datetime .timezone .utc ).isoformat ()
874+
857875 stix_relation_id = self .opencti .create_relation_if_not_exists (
858876 source_id ,
859877 source_type ,
@@ -862,11 +880,9 @@ def import_relationship(self, stix_relation):
862880 stix_relation ['relationship_type' ],
863881 stix_relation ['description' ] if 'description' in stix_relation else '' ,
864882 stix_relation [
865- 'x_opencti_first_seen' ] if 'x_opencti_first_seen' in stix_relation else datetime .datetime .utcnow ().replace (
866- microsecond = 0 , tzinfo = datetime .timezone .utc ).isoformat (),
883+ 'x_opencti_first_seen' ] if 'x_opencti_first_seen' in stix_relation else date ,
867884 stix_relation [
868- 'x_opencti_last_seen' ] if 'x_opencti_last_seen' in stix_relation else datetime .datetime .utcnow ().replace (
869- microsecond = 0 , tzinfo = datetime .timezone .utc ).isoformat (),
885+ 'x_opencti_last_seen' ] if 'x_opencti_last_seen' in stix_relation else date ,
870886 stix_relation ['x_opencti_weight' ] if 'x_opencti_weight' in stix_relation else 4 ,
871887 stix_relation ['x_opencti_role_played' ] if 'x_opencti_role_played' in stix_relation else None ,
872888 stix_relation ['x_opencti_id' ] if 'x_opencti_id' in stix_relation else None ,
@@ -947,64 +963,48 @@ def import_relationship(self, stix_relation):
947963 self .opencti .add_object_ref_to_report_if_not_exists (report_id , stix_relation_id )
948964
949965 def resolve_author (self , title ):
950- if 'fireeye' in title .lower ():
951- if 'FireEye' in self .mapping_cache :
952- return self .mapping_cache ['FireEye' ]
953- else :
954- author_id = self .opencti .create_identity_if_not_exists ('Organization' , 'FireEye' , '' )['id' ]
955- self .mapping_cache ['FireEye' ] = author_id
956- return author_id
966+ if 'fireeye' in title .lower () or 'mandiant' in title .lower ():
967+ return self .get_author ('FireEye' )
957968 if 'eset' in title .lower ():
958- if 'ESET' in self .mapping_cache :
959- return self .mapping_cache ['ESET' ]
960- else :
961- author_id = self .opencti .create_identity_if_not_exists ('Organization' , 'ESET' , '' )['id' ]
962- self .mapping_cache ['ESET' ] = author_id
963- return author_id
964- if 'unit 42' in title .lower ():
965- if 'PaloAlto' in self .mapping_cache :
966- return self .mapping_cache ['PaloAlto' ]
967- else :
968- author_id = self .opencti .create_identity_if_not_exists ('Organization' , 'Palo Alto Networks' , '' )['id' ]
969- self .mapping_cache ['PaloAlto' ] = author_id
970- return author_id
969+ return self .get_author ('ESET' )
970+ if 'dragos' in title .lower ():
971+ return self .get_author ('Dragos' )
972+ if 'us-cert' in title .lower ():
973+ return self .get_author ('US-CERT' )
974+ if 'unit 42' in title .lower () or 'unit42' in title .lower () or 'palo alto' in title .lower ():
975+ return self .get_author ('Palo Alto Networks' )
971976 if 'accenture' in title .lower ():
972- if 'Accenture' in self .mapping_cache :
973- return self .mapping_cache ['Accenture' ]
974- else :
975- author_id = self .opencti .create_identity_if_not_exists ('Organization' , 'Accenture' , '' )['id' ]
976- self .mapping_cache ['Accenture' ] = author_id
977- return author_id
977+ return self .get_author ('Accenture' )
978978 if 'symantec' in title .lower ():
979- if 'Symantec' in self .mapping_cache :
980- return self .mapping_cache ['Symantec' ]
981- else :
982- author_id = self .opencti .create_identity_if_not_exists ('Organization' , 'Symantec' , '' )['id' ]
983- self .mapping_cache ['Symantec' ] = author_id
984- return author_id
979+ return self .get_author ('Symantec' )
980+ if 'trendmicro' in title .lower () or 'trend micro' in title .lower ():
981+ return self .get_author ('Trend Micro' )
985982 if 'mcafee' in title .lower ():
986- if 'McAfee' in self .mapping_cache :
987- return self .mapping_cache ['McAfee' ]
988- else :
989- author_id = self .opencti .create_identity_if_not_exists ('Organization' , 'McAfee' , '' )['id' ]
990- self .mapping_cache ['McAfee' ] = author_id
991- return author_id
983+ return self .get_author ('McAfee' )
992984 if 'crowdstrike' in title .lower ():
993- if 'CrowdStrike' in self . mapping_cache :
994- return self . mapping_cache [ 'CrowdStrike' ]
995- else :
996- author_id = self . opencti . create_identity_if_not_exists ( 'Organization' , 'CrowdStrike' , '' )[ 'id' ]
997- self .mapping_cache [ 'CrowdStrike' ] = author_id
998- return author_id
999- if 'mitre atta&ck' in title . lower ():
1000- if 'Mitre ' in self . mapping_cache :
1001- return self .mapping_cache [ 'Mitre' ]
1002- else :
1003- author_id = self .opencti . create_identity_if_not_exists ( 'Organization' , 'The MITRE Corporation' , '' )[ 'id' ]
1004- self . mapping_cache [ 'Mitre' ] = author_id
1005- return author_id
985+ return self . get_author ( 'CrowdStrike' )
986+ if 'securelist' in title . lower () or 'kaspersky' in title . lower ():
987+ return self . get_author ( 'Kaspersky' )
988+ if 'f-secure' in title . lower ():
989+ return self .get_author ( 'F-Secure' )
990+ if 'checkpoint' in title . lower ():
991+ return self . get_author ( 'CheckPoint' )
992+ if 'talos ' in title . lower () :
993+ return self .get_author ( 'Cisco Talos' )
994+ if 'secureworks' in title . lower () :
995+ return self .get_author ( 'Dell SecureWorks' )
996+ if 'mitre att&ck' in title . lower ():
997+ return self . get_author ( 'The MITRE Corporation' )
1006998 return None
1007999
1000+ def get_author (self , name ):
1001+ if name in self .mapping_cache :
1002+ return self .mapping_cache [name ]
1003+ else :
1004+ author_id = self .opencti .create_identity_if_not_exists ('Organization' , name , '' )['id' ]
1005+ self .mapping_cache [name ] = author_id
1006+ return author_id
1007+
10081008 def import_bundle (self , stix_bundle , update = False , types = []):
10091009 # Check if the bundle is correctly formated
10101010 if 'type' not in stix_bundle or stix_bundle ['type' ] != 'bundle' :
0 commit comments