From 6e86899221ebf9bff301a183fa80224130d890f5 Mon Sep 17 00:00:00 2001 From: Kent Manley Date: Wed, 5 Oct 2022 09:55:07 -0500 Subject: [PATCH 1/6] updated file handle with encoding utf-8, allows reading multibyte characters in json files provided by Mitre. --- attack2neo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attack2neo.py b/attack2neo.py index 0eb0caf..5995f4b 100755 --- a/attack2neo.py +++ b/attack2neo.py @@ -100,7 +100,7 @@ def build_relations(obj): # # load JSON data from file try: - with open(json_file) as fh: + with open(json_file, encoding='utf-8') as fh: data = json.load(fh) fh.close() except Exception as e: From 5e22e6f974518760546616c5a9fb1825ab4d69ec Mon Sep 17 00:00:00 2001 From: Kent Manley Date: Wed, 5 Oct 2022 10:10:36 -0500 Subject: [PATCH 2/6] updated code to also grab records of type TAxxxx, where xxxxx is four digits. --- attack2neo.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/attack2neo.py b/attack2neo.py index 5995f4b..e20cd34 100755 --- a/attack2neo.py +++ b/attack2neo.py @@ -16,6 +16,7 @@ def build_label(txt): if txt.startswith('tool'): return 'Tool' if txt.startswith('attack-pattern'): return 'Technique' if txt.startswith('course-of-action'): return 'Technique' + if txt.startswith('x-mitre-tactic'): return 'Technique' return 'Unknown' # ----------------------------------------------------------------- @@ -143,7 +144,7 @@ def build_relations(obj): build_objects(obj,'x_mitre_aliases') # if JSON object is about Techniques - if args.techniques and (obj['type']=='attack-pattern' or obj['type']=='course-of-action'): + if args.techniques and (obj['type']=='attack-pattern' or obj['type']=='course-of-action' or obj['type']=='x-mitre-tactic'): gnames[ obj['id'] ] = obj['name'] build_objects(obj,None) # label = build_label(obj['type']) From 00c73bed1fc2699ffc412409dc52d4af84b39260 Mon Sep 17 00:00:00 2001 From: Kent Manley Date: Thu, 6 Oct 2022 07:30:59 -0500 Subject: [PATCH 3/6] Fixed code implementing technique_id (stored as external_id) --- attack2neo.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/attack2neo.py b/attack2neo.py index e20cd34..8bb4499 100755 --- a/attack2neo.py +++ b/attack2neo.py @@ -35,6 +35,17 @@ def build_objects(obj,key): if obj.get('created'): props['created'] = obj['created'] if obj.get('modified'): props['modified'] = obj['modified'] if obj.get('x_mitre_version'): props['version'] = obj['x_mitre_version'] + + # kem Add TechniqueID ( the T/TA numbers) from each data['object'] + if obj.get('external_references'): + for ref in obj['external_references']: + if ref.get('external_id'): +# if ref.get('external_id').startswith('T'): +# props.setdefault('technique_id', []).append(ref['external_id']) + props['technique_id'] = ref['external_id'] # capture T/TA# and change name to technique_id + else: + continue + # create node for the group node_main = Node(label, **props) # merge node to graph From e9bb553b9e1fc5aa0b32450ac47ad9faef3f3e6e Mon Sep 17 00:00:00 2001 From: Kent Manley Date: Mon, 10 Oct 2022 16:43:46 -0500 Subject: [PATCH 4/6] Move graph connection and clear code to top of file --- attack2neo.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/attack2neo.py b/attack2neo.py index 8bb4499..08566aa 100755 --- a/attack2neo.py +++ b/attack2neo.py @@ -6,6 +6,17 @@ import sys from py2neo import Graph, Node, Relationship, NodeMatcher, cypher +# +# open graph connection +graph_bolt = "bolt://127.0.0.1:7687" +graph_auth = ("neo4j","test") + +graph = Graph(graph_bolt,auth=graph_auth) + +# +# Delete existing nodes and edges +graph.delete_all() + # ----------------------------------------------------------------- # BUILD_LABEL # ----------------------------------------------------------------- @@ -120,17 +131,6 @@ def build_relations(obj): sys.stderr.write( '[ERROR] %s\n' % str(e) ) sys.exit(1) -# -# open graph connection -graph_bolt = "bolt://127.0.0.1:7687" -graph_auth = ("neo4j","test") - -graph = Graph(graph_bolt,auth=graph_auth) - -# -# Delete existing nodes and edges -graph.delete_all() - # # Global names gnames = {} From 17c3ce7c0a793dbacebbbeb3899956bb2ca92b18 Mon Sep 17 00:00:00 2001 From: Kent Manley Date: Tue, 11 Oct 2022 16:34:01 -0500 Subject: [PATCH 5/6] Commented out the graph.delete_all() function --- attack2neo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attack2neo.py b/attack2neo.py index 08566aa..ccb45ca 100755 --- a/attack2neo.py +++ b/attack2neo.py @@ -15,7 +15,7 @@ # # Delete existing nodes and edges -graph.delete_all() +# graph.delete_all() # ----------------------------------------------------------------- # BUILD_LABEL From 8aaa15ca3644d5da8d32e9058cac48a09cbcf7fa Mon Sep 17 00:00:00 2001 From: Kent Manley Date: Thu, 13 Oct 2022 11:39:16 -0500 Subject: [PATCH 6/6] Turn on the delete_all() feature --- attack2neo.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/attack2neo.py b/attack2neo.py index ccb45ca..d6b436a 100755 --- a/attack2neo.py +++ b/attack2neo.py @@ -15,7 +15,7 @@ # # Delete existing nodes and edges -# graph.delete_all() +graph.delete_all() # ----------------------------------------------------------------- # BUILD_LABEL @@ -27,7 +27,7 @@ def build_label(txt): if txt.startswith('tool'): return 'Tool' if txt.startswith('attack-pattern'): return 'Technique' if txt.startswith('course-of-action'): return 'Technique' - if txt.startswith('x-mitre-tactic'): return 'Technique' + if txt.startswith('x-mitre-tactic'): return 'Technique' # kem Added to get the TAxxxx types return 'Unknown' # ----------------------------------------------------------------- @@ -35,6 +35,8 @@ def build_label(txt): # ----------------------------------------------------------------- def build_objects(obj,key): + # kem Should object not be processed? return without processing + label = build_label(obj['type']) # add properties @@ -42,11 +44,12 @@ def build_objects(obj,key): props['name'] = obj['name'] props['id'] = obj['id'] props['type'] = obj['type'] - if obj.get('description'): props['description'] = obj['description'] # cypher.cypher_escape( obj['description'] ) - if obj.get('created'): props['created'] = obj['created'] - if obj.get('modified'): props['modified'] = obj['modified'] - if obj.get('x_mitre_version'): props['version'] = obj['x_mitre_version'] - + if obj.get('description'): props['description'] = obj['description'] # cypher.cypher_escape( obj['description'] ) + if obj.get('created'): props['created'] = obj['created'] + if obj.get('modified'): props['modified'] = obj['modified'] + if obj.get('x_mitre_version'): props['version'] = obj['x_mitre_version'] + if obj.get('x_mitre_deprecated'): props['deprecated'] = obj['x_mitre_deprecated'] # kem Capture that deprecated flag so we can check + # kem Add TechniqueID ( the T/TA numbers) from each data['object'] if obj.get('external_references'): for ref in obj['external_references']: