CVE-2020-12889: Insufficient Information (NVD-CWE-noinfo)
value: MISP MISP-maltego 1.4.4 incorrectly shares a MISP connection across users in a remote-transform use case.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 9.8
Published: 2020-05-15T18:15Z
Repository: https://github.com/MISP/MISP-maltego
Language: Python
Files changed: src/MISP_maltego/transforms/attributetoevent.py, src/MISP_maltego/transforms/common/util.py, src/MISP_maltego/transforms/eventtoattributes.py, src/MISP_maltego/transforms/galaxytoevent.py
Commit date: 2020-05-15 08:59:20 +0200
Commit message: fix: [security] fixes a security issue when used as remote transform

the MISP connection being shared by all the users
Diff: diff --git a/src/MISP_maltego/transforms/attributetoevent.py b/src/MISP_maltego/transforms/attributetoevent.py
index 14b3cbc..fc525ca 100644
--- a/src/MISP_maltego/transforms/attributetoevent.py
+++ b/src/MISP_maltego/transforms/attributetoevent.py
@@ -1,9 +1,9 @@
 from canari.maltego.entities import Unknown, Hashtag
 from canari.maltego.transform import Transform
 from MISP_maltego.transforms.common.entities import MISPGalaxy
-from MISP_maltego.transforms.common.util import check_update, get_misp_connection, event_to_entity, object_to_entity, get_attribute_in_event, get_attribute_in_object, attribute_to_entity, get_entity_property, search_galaxy_cluster, galaxycluster_to_entity, tag_matches_note_prefix
+from MISP_maltego.transforms.common.util import check_update, MISPConnection, event_to_entity, get_attribute_in_event, get_attribute_in_object, attribute_to_entity, get_entity_property, search_galaxy_cluster, galaxycluster_to_entity
 from canari.maltego.message import LinkDirection, Bookmark
 
 __author__ = 'Christophe Vandeplas'
 __copyright__ = 'Copyright 2018, MISP_maltego Project'
 __credits__ = []
@@ -24,24 +24,24 @@ class SearchInMISP(Transform):
     def do_transform(self, request, response, config):
         response += check_update(config)
         link_label = 'Search result'
 
         if 'properties.mispevent' in request.entity.fields:
-            misp = get_misp_connection(config, request.parameters)
+            conn = MISPConnection(config, request.parameters)
             # if event_id
             try:
                 if request.entity.value == '0':
                     return response
                 eventid = int(request.entity.value)
-                events_json = misp.search(controller='events', eventid=eventid, with_attachments=False)
+                events_json = conn.misp.search(controller='events', eventid=eventid, with_attachments=False)
                 for e in events_json:
                     response += event_to_entity(e, link_label=link_label, link_direction=LinkDirection.OutputToInput)
                 return response
             except ValueError:
                 pass
             # if event_info string as value
-            events_json = misp.search(controller='events', eventinfo=request.entity.value, with_attachments=False)
+            events_json = conn.misp.search(controller='events', eventinfo=request.entity.value, with_attachments=False)
             for e in events_json:
                 response += event_to_entity(e, link_label=link_label, link_direction=LinkDirection.OutputToInput)
             return response
 
         # From galaxy or Hashtag
@@ -66,24 +66,24 @@ class SearchInMISP(Transform):
             # from Hashtag search also in tags
             if 'properties.temp' in request.entity.fields:
                 keyword = get_entity_property(request.entity, 'Temp')
                 if not keyword:
                     keyword = request.entity.value
-                misp = get_misp_connection(config, request.parameters)
-                result = misp.direct_call('tags/search', {'name': keyword})
+                conn = MISPConnection(config, request.parameters)
+                result = conn.misp.direct_call('tags/search', {'name': keyword})
                 for t in result:
                     # skip misp-galaxies as we have processed them earlier on
                     if t['Tag']['name'].startswith('misp-galaxy'):
                         continue
                     # In this case we do not filter away those we add as notes, as people might want to pivot on it explicitly.
                     response += Hashtag(t['Tag']['name'], link_label=link_label, bookmark=Bookmark.Green)
 
             return response
 
         # for all other normal entities
-        misp = get_misp_connection(config, request.parameters)
-        events_json = misp.search(controller='events', value=request.entity.value, with_attachments=False)
+        conn = MISPConnection(config, request.parameters)
+        events_json = conn.misp.search(controller='events', value=request.entity.value, with_attachments=False)
         # we need to do really rebuild the Entity from scratch as request.entity is of type Unknown
         for e in events_json:
             # find the value as attribute
             attr = get_attribute_in_event(e, request.entity.value, substring=True)
             if attr:
@@ -91,11 +91,11 @@ class SearchInMISP(Transform):
                     response += item
             # find the value as object, and return the object
             if 'Object' in e['Event']:
                 for o in e['Event']['Object']:
                     if get_attribute_in_object(o, attribute_value=request.entity.value, substring=True).get('value'):
-                        response += object_to_entity(o, link_label=link_label)
+                        response += conn.object_to_entity(o, link_label=link_label)
 
         return response
 
 # placeholder for https://github.com/MISP/MISP-maltego/issues/11
 # waiting for support of CIDR search through the REST API
@@ -135,41 +135,41 @@ class AttributeToEvent(Transform):
 
         if 'ipv4-range' in request.entity.fields:
             # placeholder for https://github.com/MISP/MISP-maltego/issues/11
             pass
 
-        misp = get_misp_connection(config, request.parameters)
+        conn = MISPConnection(config, request.parameters)
         # from Galaxy
         if 'properties.mispgalaxy' in request.entity.fields:
             tag_name = get_entity_property(request.entity, 'tag_name')
             if not tag_name:
                 tag_name = request.entity.value
-            events_json = misp.search(controller='events', tags=tag_name, with_attachments=False)
+            events_json = conn.misp.search(controller='events', tags=tag_name, with_attachments=False)
             for e in events_json:
                 response += event_to_entity(e, link_direction=LinkDirection.OutputToInput)
             return response
         # from Object
         elif 'properties.mispobject' in request.entity.fields:
             if request.entity.fields.get('event_id'):
-                events_json = misp.search(controller='events', eventid=request.entity.fields.get('event_id').value, with_attachments=False)
+                events_json = conn.misp.search(controller='events', eventid=request.entity.fields.get('event_id').value, with_attachments=False)
                 for e in events_json:
                     response += event_to_entity(e, link_direction=LinkDirection.OutputToInput)
                 return response
             else:
                 return response
         # from Hashtag
         elif 'properties.temp' in request.entity.fields:
             tag_name = get_entity_property(request.entity, 'Temp')
             if not tag_name:
                 tag_name = request.entity.value
-            events_json = misp.search(controller='events', tags=tag_name, with_attachments=False)
+            events_json = conn.misp.search(controller='events', tags=tag_name, with_attachments=False)
             for e in events_json:
                 response += event_to_entity(e, link_direction=LinkDirection.OutputToInput)
             return response
         # standard Entities (normal attributes)
         else:
-            events_json = misp.search(controller='events', value=request.entity.value, with_attachments=False)
+            events_json = conn.misp.search(controller='events', value=request.entity.value, with_attachments=False)
 
         # return the MISPEvent or MISPObject of the attribute
         for e in events_json:
             # find the value as attribute
             attr = get_attribute_in_event(e, request.entity.value)
@@ -177,8 +177,8 @@ class AttributeToEvent(Transform):
                 response += event_to_entity(e, link_direction=LinkDirection.OutputToInput)
             # find the value as object
             if 'Object' in e['Event']:
                 for o in e['Event']['Object']:
                     if get_attribute_in_object(o, attribute_value=request.entity.value).get('value'):
-                        response += object_to_entity(o, link_direction=LinkDirection.OutputToInput)
+                        response += conn.object_to_entity(o, link_direction=LinkDirection.OutputToInput)
 
         return response
diff --git a/src/MISP_maltego/transforms/common/util.py b/src/MISP_maltego/transforms/common/util.py
index bb6cecf..c34bb4c 100644
--- a/src/MISP_maltego/transforms/common/util.py
+++ b/src/MISP_maltego/transforms/common/util.py
@@ -16,11 +16,10 @@ import time
 
 __version__ = '1.4.4'  # also update version in setup.py
 
 tag_note_prefixes = ['tlp:', 'PAP:', 'de-vs:', 'euci:', 'fr-classif:', 'nato:']
 
-misp_connection = None
 update_url = 'https://raw.githubusercontent.com/MISP/MISP-maltego/master/setup.py'
 local_path_root = os.path.join(tempfile.gettempdir(), 'MISP-maltego')
 local_path_version = os.path.join(local_path_root, 'versioncheck')
 if not os.path.exists(local_path_root):
     os.mkdir(local_path_root)
@@ -62,41 +61,120 @@ def check_update(config):
                     return UIMessage(message, type=UIMessageType.Fatal)
                 break
     return None
 
 
-def get_misp_connection(config=None, parameters=None):
-    global misp_connection
-    if misp_connection:
-        return misp_connection
-    if not config:
-        raise MaltegoException("ERROR: MISP connection not yet established, and config not provided as parameter.")
-    misp_verify = True
-    misp_debug = False
-    misp_url = None
-    misp_key = None
-    try:
-        if is_local_exec_mode():
-            misp_url = config['MISP_maltego.local.misp_url']
-            misp_key = config['MISP_maltego.local.misp_key']
-            if config['MISP_maltego.local.misp_verify'] in ['False', 'false', 0, 'no', 'No']:
-                misp_verify = False
-            if config['MISP_maltego.local.misp_debug'] in ['True', 'true', 1, 'yes', 'Yes']:
-                misp_debug = True
-        if is_remote_exec_mode():
+class MISPConnection():
+    def __init__(self, config=None, parameters=None):
+        self.misp = None
+
+        if not config:
+            raise MaltegoException("ERROR: MISP connection not yet established, and config not provided as parameter.")
+        misp_verify = True
+        misp_debug = False
+        misp_url = None
+        misp_key = None
+        try:
+            if is_local_exec_mode():
+                misp_url = config['MISP_maltego.local.misp_url']
+                misp_key = config['MISP_maltego.local.misp_key']
+                if config['MISP_maltego.local.misp_verify'] in ['False', 'false', 0, 'no', 'No']:
+                    misp_verify = False
+                if config['MISP_maltego.local.misp_debug'] in ['True', 'true', 1, 'yes', 'Yes']:
+                    misp_debug = True
+            else:
+                try:
+                    misp_url = parameters['mispurl'].value
+                    misp_key = parameters['mispkey'].value
+                except AttributeError:
+                    raise MaltegoException("ERROR: mispurl and mispkey need to be set to something valid")
+            self.misp = PyMISP(misp_url, misp_key, misp_verify, 'json', misp_debug, tool='misp_maltego')
+        except Exception:
+            if is_local_exec_mode():
+                raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your MISP_Maltego.conf settings.")
+            else:
+                raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your settings (MISP URL and API key), and ensure the MISP server is reachable from the internet.")
+
+    def object_to_entity(self, o, link_label=None, link_direction=LinkDirection.InputToOutput):
+        # find a nice icon for it
+        try:
+            icon_url = mapping_object_icon[o['name']]
+        except KeyError:
+            # it's not in our mapping, just ignore and leave the default icon
+            icon_url = None
+        # Generate a human readable display-name:
+        # - find the first RequiredOneOf that exists
+        # - if none, use the first RequiredField
+        # LATER further finetune the human readable version of this object
+        o_template = self.misp.get_object_template(o['template_uuid'])
+        human_readable = None
+        try:
+            found = False
+            while not found:  # the while loop is broken once something is found, or the requiredOneOf has no elements left
+                required_ote_type = o_template['ObjectTemplate']['requirements']['requiredOneOf'].pop(0)
+                for ote in o_template['ObjectTemplateElement']:
+                    if ote['object_relation'] == required_ote_type:
+                        required_a_type = ote['type']
+                        break
+                for a in o['Attribute']:
+                    if a['type'] == required_a_type:
+                        human_readable = '{}:\n{}'.format(o['name'], a['value'])
+                        found = True
+                        break
+        except Exception:
+            pass
+        if not human_readable:
             try:
-                misp_url = parameters['mispurl'].value
-                misp_key = parameters['mispkey'].value
-            except AttributeError:
-                raise MaltegoException("ERROR: mispurl and mispkey need to be set to something valid")
-        misp_connection = PyMISP(misp_url, misp_key, misp_verify, 'json', misp_debug, tool='misp_maltego')
-    except Exception:
-        if is_local_exec_mode():
-            raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your MISP_Maltego.conf settings.")
-        if is_remote_exec_mode():
-            raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your settings (MISP URL and API key), and ensure the MISP server is reachable from the internet.")
-    return misp_connection
+                found = False
+                parts = []
+                for required_ote_type in o_template['ObjectTemplate']['requirements']['required']:
+                    for ote in o_template['ObjectTemplateElement']:
+                        if ote['object_relation'] == required_ote_type:
+                            required_a_type = ote['type']
+                            break
+                    for a in o['Attribute']:
+                        if a['type'] == required_a_type:
+                            parts.append(a['value'])
+                            break
+                human_readable = '{}:\n{}'.format(o['name'], '|'.join(parts))
+            except Exception:
+                human_readable = o['name']
+        return MISPObject(
+            human_readable,
+            uuid=o['uuid'],
+            event_id=int(o['event_id']),
+            meta_category=o.get('meta_category'),
+            description=o.get('description'),
+            comment=o.get('comment'),
+            icon_url=icon_url,
+            link_label=link_label,
+            link_direction=link_direction,
+            bookmark=Bookmark.Green
+        )
+
+    def object_to_relations(self, o, e):
+        # process forward and reverse references, so just loop over all the objects of the event
+        if 'Object' in e['Event']:
+            for eo in e['Event']['Object']:
+                if 'ObjectReference' in eo:
+                    for ref in eo['ObjectReference']:
+                        # we have found original object. Expand to the related object and attributes
+                        if eo['uuid'] == o['uuid']:
+                            # the reference is an Object
+                            if ref.get('Object'):
+                                # get the full object in the event, as our objectReference included does not contain everything we need
+                                sub_object = get_object_in_event(ref['Object']['uuid'], e)
+                                yield self.object_to_entity(sub_object, link_label=ref['relationship_type'])
+                            # the reference is an Attribute
+                            if ref.get('Attribute'):
+                                ref['Attribute']['event_id'] = ref['event_id']   # LATER remove this ugly workaround - object can't be requested directly from MISP using the uuid, and to find a full object we need the event_id
+                                for item in attribute_to_entity(ref['Attribute'], link_label=ref['relationship_type']):
+                                    yield item
+
+                        # reverse-lookup - this is another objects relating the original object
+                        if ref['referenced_uuid'] == o['uuid']:
+                            yield self.object_to_entity(eo, link_label=ref['relationship_type'], link_direction=LinkDirection.OutputToInput)
 
 
 def entity_obj_to_entity(entity_obj, v, t, **kwargs):
     if entity_obj == Hash:
         return entity_obj(v, _type=t, **kwargs)  # LATER type is conflicting with type of Entity, Report this as bug see line 326 /usr/local/lib/python3.5/dist-packages/canari/maltego/entities.py
@@ -174,69 +252,10 @@ def attribute_to_entity(a, link_label=None, event_tags=[], only_self=False):
     # not supported in our maltego mapping are not handled
 
     # LATER : relationships from attributes - not yet supported by MISP yet, but there are references in the datamodel
 
 
-def object_to_entity(o, link_label=None, link_direction=LinkDirection.InputToOutput):
-    misp = get_misp_connection()
-    # find a nice icon for it
-    try:
-        icon_url = mapping_object_icon[o['name']]
-    except KeyError:
-        # it's not in our mapping, just ignore and leave the default icon
-        icon_url = None
-    # Generate a human readable display-name:
-    # - find the first RequiredOneOf that exists
-    # - if none, use the first RequiredField
-    # LATER further finetune the human readable version of this object
-    o_template = misp.get_object_template(o['template_uuid'])
-    human_readable = None
-    try:
-        found = False
-        while not found:  # the while loop is broken once something is found, or the requiredOneOf has no elements left
-            required_ote_type = o_template['ObjectTemplate']['requirements']['requiredOneOf'].pop(0)
-            for ote in o_template['ObjectTemplateElement']:
-                if ote['object_relation'] == required_ote_type:
-                    required_a_type = ote['type']
-                    break
-            for a in o['Attribute']:
-                if a['type'] == required_a_type:
-                    human_readable = '{}:\n{}'.format(o['name'], a['value'])
-                    found = True
-                    break
-    except Exception:
-        pass
-    if not human_readable:
-        try:
-            found = False
-            parts = []
-            for required_ote_type in o_template['ObjectTemplate']['requirements']['required']:
-                for ote in o_template['ObjectTemplateElement']:
-                    if ote['object_relation'] == required_ote_type:
-                        required_a_type = ote['type']
-                        break
-                for a in o['Attribute']:
-                    if a['type'] == required_a_type:
-                        parts.append(a['value'])
-                        break
-            human_readable = '{}:\n{}'.format(o['name'], '|'.join(parts))
-        except Exception:
-            human_readable = o['name']
-    return MISPObject(
-        human_readable,
-        uuid=o['uuid'],
-        event_id=int(o['event_id']),
-        meta_category=o.get('meta_category'),
-        description=o.get('description'),
-        comment=o.get('comment'),
-        icon_url=icon_url,
-        link_label=link_label,
-        link_direction=link_direction,
-        bookmark=Bookmark.Green
-    )
-
-
 def object_to_attributes(o, e):
     # first process attributes from an object that belong together (eg: first-name + last-name), and remove them from the list
     if o['name'] == 'person':
         first_name = get_attribute_in_object(o, attribute_type='first-name', drop=True).get('value')
         last_name = get_attribute_in_object(o, attribute_type='last-name', drop=True).get('value')
@@ -246,34 +265,10 @@ def object_to_attributes(o, e):
     for a in o['Attribute']:
         for item in attribute_to_entity(a):
             yield item
 
 
-def object_to_relations(o, e):
-    # process forward and reverse references, so just loop over all the objects of the event
-    if 'Object' in e['Event']:
-        for eo in e['Event']['Object']:
-            if 'ObjectReference' in eo:
-                for ref in eo['ObjectReference']:
-                    # we have found original object. Expand to the related object and attributes
-                    if eo['uuid'] == o['uuid']:
-                        # the reference is an Object
-                        if ref.get('Object'):
-                            # get the full object in the event, as our objectReference included does not contain everything we need
-                            sub_object = get_object_in_event(ref['Object']['uuid'], e)
-                            yield object_to_entity(sub_object, link_label=ref['relationship_type'])
-                        # the reference is an Attribute
-                        if ref.get('Attribute'):
-                            ref['Attribute']['event_id'] = ref['event_id']   # LATER remove this ugly workaround - object can't be requested directly from MISP using the uuid, and to find a full object we need the event_id
-                            for item in attribute_to_entity(ref['Attribute'], link_label=ref['relationship_type']):
-                                yield item
-
-                    # reverse-lookup - this is another objects relating the original object
-                    if ref['referenced_uuid'] == o['uuid']:
-                        yield object_to_entity(eo, link_label=ref['relationship_type'], link_direction=LinkDirection.OutputToInput)
-
-
 def get_object_in_event(uuid, e):
     for o in e['Event']['Object']:
         if o['uuid'] == uuid:
             return o
 
diff --git a/src/MISP_maltego/transforms/eventtoattributes.py b/src/MISP_maltego/transforms/eventtoattributes.py
index 7aa6a9b..b0b0012 100644
--- a/src/MISP_maltego/transforms/eventtoattributes.py
+++ b/src/MISP_maltego/transforms/eventtoattributes.py
@@ -1,9 +1,9 @@
 from canari.maltego.entities import Hashtag
 from canari.maltego.transform import Transform
 from MISP_maltego.transforms.common.entities import MISPEvent, MISPObject
-from MISP_maltego.transforms.common.util import check_update, get_misp_connection, attribute_to_entity, event_to_entity, galaxycluster_to_entity, object_to_entity, object_to_attributes, object_to_relations, tag_matches_note_prefix
+from MISP_maltego.transforms.common.util import check_update, MISPConnection, attribute_to_entity, event_to_entity, galaxycluster_to_entity, object_to_attributes, tag_matches_note_prefix
 from canari.maltego.message import LinkStyle
 
 
 __author__ = 'Christophe Vandeplas'
 __copyright__ = 'Copyright 2018, MISP_maltego Project'
@@ -13,34 +13,34 @@ __license__ = 'AGPLv3'
 __version__ = '0.1'
 __maintainer__ = 'Christophe Vandeplas'
 __email__ = 'christophe@vandeplas.com'
 __status__ = 'Development'
 
-# FIXME have a more human readable version of the MISP event value in the graph. change entity + event_to_entity + do_transform
+# TODO have a more human readable version of the MISP event value in the graph. change entity + event_to_entity + do_transform
 
 
 class EventToTransform(Transform):
     input_type = None
     """Generic EventTo class containing multiple reusable functions for the subclasses."""
 
     def __init__(self):
         self.request = None
         self.response = None
         self.config = None
-        self.misp = None
+        self.conn = None
         self.event_json = None
         self.event_tags = None
 
     def do_transform(self, request, response, config):
         self.request = request
         self.response = response
         self.config = config
         self.response += check_update(config)
         maltego_misp_event = request.entity
-        self.misp = get_misp_connection(config, request.parameters)
+        self.conn = MISPConnection(config, request.parameters)
         event_id = maltego_misp_event.id
-        search_result = self.misp.search(controller='events', eventid=event_id, with_attachments=False)
+        search_result = self.conn.misp.search(controller='events', eventid=event_id, with_attachments=False)
         if search_result:
             self.event_json = search_result.pop()
         else:
             return False
 
@@ -74,11 +74,11 @@ class EventToTransform(Transform):
                 if entity:
                     self.response += entity
 
     def gen_response_objects(self):
         for o in self.event_json['Event']['Object']:
-            self.response += object_to_entity(o)
+            self.response += self.conn.object_to_entity(o)
 
     def gen_response_relations(self):
         for e in self.event_json['Event']['RelatedEvent']:
             self.response += event_to_entity(e, link_style=LinkStyle.DashDot)
 
@@ -167,18 +167,18 @@ class ObjectToAttributes(Transform):
     remote = True
 
     def do_transform(self, request, response, config):
         response += check_update(config)
         maltego_object = request.entity
-        misp = get_misp_connection(config, request.parameters)
-        event_json = misp.get_event(maltego_object.event_id)
+        conn = MISPConnection(config, request.parameters)
+        event_json = conn.misp.get_event(maltego_object.event_id)
         for o in event_json['Event']['Object']:
             if o['uuid'] == maltego_object.uuid:
                 for entity in object_to_attributes(o, event_json):
                     if entity:
                         response += entity
-                for entity in object_to_relations(o, event_json):
+                for entity in conn.object_to_relations(o, event_json):
                     if entity:
                         response += entity
 
         return response
 
@@ -190,14 +190,14 @@ class ObjectToRelations(Transform):
     remote = True
 
     def do_transform(self, request, response, config):
         response += check_update(config)
         maltego_object = request.entity
-        misp = get_misp_connection(config, request.parameters)
-        event_json = misp.get_event(maltego_object.event_id)
+        conn = MISPConnection(config, request.parameters)
+        event_json = conn.misp.get_event(maltego_object.event_id)
         for o in event_json['Event']['Object']:
             if o['uuid'] == maltego_object.uuid:
-                for entity in object_to_relations(o, event_json):
+                for entity in conn.object_to_relations(o, event_json):
                     if entity:
                         response += entity
 
         return response
diff --git a/src/MISP_maltego/transforms/galaxytoevent.py b/src/MISP_maltego/transforms/galaxytoevent.py
index 0468a81..785bad4 100644
--- a/src/MISP_maltego/transforms/galaxytoevent.py
+++ b/src/MISP_maltego/transforms/galaxytoevent.py
@@ -1,8 +1,8 @@
 from canari.maltego.transform import Transform
 from MISP_maltego.transforms.common.entities import MISPEvent, MISPGalaxy, ThreatActor, Software, AttackTechnique
-from MISP_maltego.transforms.common.util import check_update, get_misp_connection, galaxycluster_to_entity, get_galaxy_cluster, get_galaxies_relating, search_galaxy_cluster, mapping_galaxy_icon
+from MISP_maltego.transforms.common.util import check_update, MISPConnection, galaxycluster_to_entity, get_galaxy_cluster, get_galaxies_relating, search_galaxy_cluster, mapping_galaxy_icon
 from canari.maltego.message import UIMessageType, UIMessage, LinkDirection
 
 
 __author__ = 'Christophe Vandeplas'
 __copyright__ = 'Copyright 2018, MISP_maltego Project'
@@ -22,16 +22,16 @@ class GalaxyToEvents(Transform):
     input_type = MISPGalaxy
     remote = True
 
     def do_transform(self, request, response, config):
         response += check_update(config)
-        misp = get_misp_connection(config, request.parameters)
+        conn = MISPConnection(config, request.parameters)
         if request.entity.tag_name:
             tag_name = request.entity.tag_name
         else:
             tag_name = request.entity.value
-        events_json = misp.search(controller='events', tags=tag_name, with_attachments=False)
+        events_json = conn.misp.search(controller='events', tags=tag_name, with_attachments=False)
         for e in events_json:
             response += MISPEvent(e['Event']['id'], uuid=e['Event']['uuid'], info=e['Event']['info'], link_direction=LinkDirection.OutputToInput)
         return response
 
 

Vulnerable code: from MISP_maltego.transforms.common.util import check_update, get_misp_connection, event_to_entity, object_to_entity, get_attribute_in_event, get_attribute_in_object, attribute_to_entity, get_entity_property, search_galaxy_cluster, galaxycluster_to_entity, tag_matches_note_prefix
            misp = get_misp_connection(config, request.parameters)
                events_json = misp.search(controller='events', eventid=eventid, with_attachments=False)
            events_json = misp.search(controller='events', eventinfo=request.entity.value, with_attachments=False)
                misp = get_misp_connection(config, request.parameters)
                result = misp.direct_call('tags/search', {'name': keyword})
        misp = get_misp_connection(config, request.parameters)
        events_json = misp.search(controller='events', value=request.entity.value, with_attachments=False)
                        response += object_to_entity(o, link_label=link_label)
        misp = get_misp_connection(config, request.parameters)
            events_json = misp.search(controller='events', tags=tag_name, with_attachments=False)
                events_json = misp.search(controller='events', eventid=request.entity.fields.get('event_id').value, with_attachments=False)
            events_json = misp.search(controller='events', tags=tag_name, with_attachments=False)
            events_json = misp.search(controller='events', value=request.entity.value, with_attachments=False)
                        response += object_to_entity(o, link_direction=LinkDirection.OutputToInput)
misp_connection = None
def get_misp_connection(config=None, parameters=None):
    global misp_connection
    if misp_connection:
        return misp_connection
    if not config:
        raise MaltegoException("ERROR: MISP connection not yet established, and config not provided as parameter.")
    misp_verify = True
    misp_debug = False
    misp_url = None
    misp_key = None
    try:
        if is_local_exec_mode():
            misp_url = config['MISP_maltego.local.misp_url']
            misp_key = config['MISP_maltego.local.misp_key']
            if config['MISP_maltego.local.misp_verify'] in ['False', 'false', 0, 'no', 'No']:
                misp_verify = False
            if config['MISP_maltego.local.misp_debug'] in ['True', 'true', 1, 'yes', 'Yes']:
                misp_debug = True
        if is_remote_exec_mode():
                misp_url = parameters['mispurl'].value
                misp_key = parameters['mispkey'].value
            except AttributeError:
                raise MaltegoException("ERROR: mispurl and mispkey need to be set to something valid")
        misp_connection = PyMISP(misp_url, misp_key, misp_verify, 'json', misp_debug, tool='misp_maltego')
    except Exception:
        if is_local_exec_mode():
            raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your MISP_Maltego.conf settings.")
        if is_remote_exec_mode():
            raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your settings (MISP URL and API key), and ensure the MISP server is reachable from the internet.")
    return misp_connection
def object_to_entity(o, link_label=None, link_direction=LinkDirection.InputToOutput):
    misp = get_misp_connection()
    # find a nice icon for it
    try:
        icon_url = mapping_object_icon[o['name']]
    except KeyError:
        # it's not in our mapping, just ignore and leave the default icon
        icon_url = None
    # Generate a human readable display-name:
    # - find the first RequiredOneOf that exists
    # - if none, use the first RequiredField
    # LATER further finetune the human readable version of this object
    o_template = misp.get_object_template(o['template_uuid'])
    human_readable = None
    try:
        found = False
        while not found:  # the while loop is broken once something is found, or the requiredOneOf has no elements left
            required_ote_type = o_template['ObjectTemplate']['requirements']['requiredOneOf'].pop(0)
            for ote in o_template['ObjectTemplateElement']:
                if ote['object_relation'] == required_ote_type:
                    required_a_type = ote['type']
                    break
            for a in o['Attribute']:
                if a['type'] == required_a_type:
                    human_readable = '{}:\n{}'.format(o['name'], a['value'])
                    found = True
                    break
    except Exception:
        pass
    if not human_readable:
        try:
            found = False
            parts = []
            for required_ote_type in o_template['ObjectTemplate']['requirements']['required']:
                for ote in o_template['ObjectTemplateElement']:
                    if ote['object_relation'] == required_ote_type:
                        required_a_type = ote['type']
                        break
                for a in o['Attribute']:
                    if a['type'] == required_a_type:
                        parts.append(a['value'])
                        break
            human_readable = '{}:\n{}'.format(o['name'], '|'.join(parts))
        except Exception:
            human_readable = o['name']
    return MISPObject(
        human_readable,
        uuid=o['uuid'],
        event_id=int(o['event_id']),
        meta_category=o.get('meta_category'),
        description=o.get('description'),
        comment=o.get('comment'),
        icon_url=icon_url,
        link_label=link_label,
        link_direction=link_direction,
        bookmark=Bookmark.Green
    )


def object_to_relations(o, e):
    # process forward and reverse references, so just loop over all the objects of the event
    if 'Object' in e['Event']:
        for eo in e['Event']['Object']:
            if 'ObjectReference' in eo:
                for ref in eo['ObjectReference']:
                    # we have found original object. Expand to the related object and attributes
                    if eo['uuid'] == o['uuid']:
                        # the reference is an Object
                        if ref.get('Object'):
                            # get the full object in the event, as our objectReference included does not contain everything we need
                            sub_object = get_object_in_event(ref['Object']['uuid'], e)
                            yield object_to_entity(sub_object, link_label=ref['relationship_type'])
                        # the reference is an Attribute
                        if ref.get('Attribute'):
                            ref['Attribute']['event_id'] = ref['event_id']   # LATER remove this ugly workaround - object can't be requested directly from MISP using the uuid, and to find a full object we need the event_id
                            for item in attribute_to_entity(ref['Attribute'], link_label=ref['relationship_type']):
                                yield item

                    # reverse-lookup - this is another objects relating the original object
                    if ref['referenced_uuid'] == o['uuid']:
                        yield object_to_entity(eo, link_label=ref['relationship_type'], link_direction=LinkDirection.OutputToInput)


from MISP_maltego.transforms.common.util import check_update, get_misp_connection, attribute_to_entity, event_to_entity, galaxycluster_to_entity, object_to_entity, object_to_attributes, object_to_relations, tag_matches_note_prefix
# FIXME have a more human readable version of the MISP event value in the graph. change entity + event_to_entity + do_transform
        self.misp = None
        self.misp = get_misp_connection(config, request.parameters)
        search_result = self.misp.search(controller='events', eventid=event_id, with_attachments=False)
            self.response += object_to_entity(o)
        misp = get_misp_connection(config, request.parameters)
        event_json = misp.get_event(maltego_object.event_id)
                for entity in object_to_relations(o, event_json):
        misp = get_misp_connection(config, request.parameters)
        event_json = misp.get_event(maltego_object.event_id)
                for entity in object_to_relations(o, event_json):
from MISP_maltego.transforms.common.util import check_update, get_misp_connection, galaxycluster_to_entity, get_galaxy_cluster, get_galaxies_relating, search_galaxy_cluster, mapping_galaxy_icon
        misp = get_misp_connection(config, request.parameters)
        events_json = misp.search(controller='events', tags=tag_name, with_attachments=False)
Fixed code: from MISP_maltego.transforms.common.util import check_update, MISPConnection, event_to_entity, get_attribute_in_event, get_attribute_in_object, attribute_to_entity, get_entity_property, search_galaxy_cluster, galaxycluster_to_entity
            conn = MISPConnection(config, request.parameters)
                events_json = conn.misp.search(controller='events', eventid=eventid, with_attachments=False)
            events_json = conn.misp.search(controller='events', eventinfo=request.entity.value, with_attachments=False)
                conn = MISPConnection(config, request.parameters)
                result = conn.misp.direct_call('tags/search', {'name': keyword})
        conn = MISPConnection(config, request.parameters)
        events_json = conn.misp.search(controller='events', value=request.entity.value, with_attachments=False)
                        response += conn.object_to_entity(o, link_label=link_label)
        conn = MISPConnection(config, request.parameters)
            events_json = conn.misp.search(controller='events', tags=tag_name, with_attachments=False)
                events_json = conn.misp.search(controller='events', eventid=request.entity.fields.get('event_id').value, with_attachments=False)
            events_json = conn.misp.search(controller='events', tags=tag_name, with_attachments=False)
            events_json = conn.misp.search(controller='events', value=request.entity.value, with_attachments=False)
                        response += conn.object_to_entity(o, link_direction=LinkDirection.OutputToInput)
class MISPConnection():
    def __init__(self, config=None, parameters=None):
        self.misp = None

        if not config:
            raise MaltegoException("ERROR: MISP connection not yet established, and config not provided as parameter.")
        misp_verify = True
        misp_debug = False
        misp_url = None
        misp_key = None
        try:
            if is_local_exec_mode():
                misp_url = config['MISP_maltego.local.misp_url']
                misp_key = config['MISP_maltego.local.misp_key']
                if config['MISP_maltego.local.misp_verify'] in ['False', 'false', 0, 'no', 'No']:
                    misp_verify = False
                if config['MISP_maltego.local.misp_debug'] in ['True', 'true', 1, 'yes', 'Yes']:
                    misp_debug = True
            else:
                try:
                    misp_url = parameters['mispurl'].value
                    misp_key = parameters['mispkey'].value
                except AttributeError:
                    raise MaltegoException("ERROR: mispurl and mispkey need to be set to something valid")
            self.misp = PyMISP(misp_url, misp_key, misp_verify, 'json', misp_debug, tool='misp_maltego')
        except Exception:
            if is_local_exec_mode():
                raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your MISP_Maltego.conf settings.")
            else:
                raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your settings (MISP URL and API key), and ensure the MISP server is reachable from the internet.")

    def object_to_entity(self, o, link_label=None, link_direction=LinkDirection.InputToOutput):
        # find a nice icon for it
        try:
            icon_url = mapping_object_icon[o['name']]
        except KeyError:
            # it's not in our mapping, just ignore and leave the default icon
            icon_url = None
        # Generate a human readable display-name:
        # - find the first RequiredOneOf that exists
        # - if none, use the first RequiredField
        # LATER further finetune the human readable version of this object
        o_template = self.misp.get_object_template(o['template_uuid'])
        human_readable = None
        try:
            found = False
            while not found:  # the while loop is broken once something is found, or the requiredOneOf has no elements left
                required_ote_type = o_template['ObjectTemplate']['requirements']['requiredOneOf'].pop(0)
                for ote in o_template['ObjectTemplateElement']:
                    if ote['object_relation'] == required_ote_type:
                        required_a_type = ote['type']
                        break
                for a in o['Attribute']:
                    if a['type'] == required_a_type:
                        human_readable = '{}:\n{}'.format(o['name'], a['value'])
                        found = True
                        break
        except Exception:
            pass
        if not human_readable:
                found = False
                parts = []
                for required_ote_type in o_template['ObjectTemplate']['requirements']['required']:
                    for ote in o_template['ObjectTemplateElement']:
                        if ote['object_relation'] == required_ote_type:
                            required_a_type = ote['type']
                            break
                    for a in o['Attribute']:
                        if a['type'] == required_a_type:
                            parts.append(a['value'])
                            break
                human_readable = '{}:\n{}'.format(o['name'], '|'.join(parts))
            except Exception:
                human_readable = o['name']
        return MISPObject(
            human_readable,
            uuid=o['uuid'],
            event_id=int(o['event_id']),
            meta_category=o.get('meta_category'),
            description=o.get('description'),
            comment=o.get('comment'),
            icon_url=icon_url,
            link_label=link_label,
            link_direction=link_direction,
            bookmark=Bookmark.Green
        )

    def object_to_relations(self, o, e):
        # process forward and reverse references, so just loop over all the objects of the event
        if 'Object' in e['Event']:
            for eo in e['Event']['Object']:
                if 'ObjectReference' in eo:
                    for ref in eo['ObjectReference']:
                        # we have found original object. Expand to the related object and attributes
                        if eo['uuid'] == o['uuid']:
                            # the reference is an Object
                            if ref.get('Object'):
                                # get the full object in the event, as our objectReference included does not contain everything we need
                                sub_object = get_object_in_event(ref['Object']['uuid'], e)
                                yield self.object_to_entity(sub_object, link_label=ref['relationship_type'])
                            # the reference is an Attribute
                            if ref.get('Attribute'):
                                ref['Attribute']['event_id'] = ref['event_id']   # LATER remove this ugly workaround - object can't be requested directly from MISP using the uuid, and to find a full object we need the event_id
                                for item in attribute_to_entity(ref['Attribute'], link_label=ref['relationship_type']):
                                    yield item

                        # reverse-lookup - this is another objects relating the original object
                        if ref['referenced_uuid'] == o['uuid']:
                            yield self.object_to_entity(eo, link_label=ref['relationship_type'], link_direction=LinkDirection.OutputToInput)
from MISP_maltego.transforms.common.util import check_update, MISPConnection, attribute_to_entity, event_to_entity, galaxycluster_to_entity, object_to_attributes, tag_matches_note_prefix
# TODO have a more human readable version of the MISP event value in the graph. change entity + event_to_entity + do_transform
        self.conn = None
        self.conn = MISPConnection(config, request.parameters)
        search_result = self.conn.misp.search(controller='events', eventid=event_id, with_attachments=False)
            self.response += self.conn.object_to_entity(o)
        conn = MISPConnection(config, request.parameters)
        event_json = conn.misp.get_event(maltego_object.event_id)
                for entity in conn.object_to_relations(o, event_json):
        conn = MISPConnection(config, request.parameters)
        event_json = conn.misp.get_event(maltego_object.event_id)
                for entity in conn.object_to_relations(o, event_json):
from MISP_maltego.transforms.common.util import check_update, MISPConnection, galaxycluster_to_entity, get_galaxy_cluster, get_galaxies_relating, search_galaxy_cluster, mapping_galaxy_icon
        conn = MISPConnection(config, request.parameters)
        events_json = conn.misp.search(controller='events', tags=tag_name, with_attachments=False)