diff --git a/src/MISP_maltego/resources/etc/MISP_maltego.conf b/src/MISP_maltego/resources/etc/MISP_maltego.conf index 91339ba..5518662 100644 --- a/src/MISP_maltego/resources/etc/MISP_maltego.conf +++ b/src/MISP_maltego/resources/etc/MISP_maltego.conf @@ -5,4 +5,6 @@ misp_key = very_secret_key misp_verify = True misp_debug = False +check_updates = True + [MISP_maltego.remote] diff --git a/src/MISP_maltego/transforms/attributetoevent.py b/src/MISP_maltego/transforms/attributetoevent.py index 30bb2a6..04fe59d 100644 --- a/src/MISP_maltego/transforms/attributetoevent.py +++ b/src/MISP_maltego/transforms/attributetoevent.py @@ -1,7 +1,7 @@ from canari.maltego.entities import Unknown from canari.maltego.transform import Transform # from canari.framework import EnableDebugWindow -from MISP_maltego.transforms.common.util import get_misp_connection, event_to_entity, object_to_entity, get_attribute_in_event, get_attribute_in_object, attribute_to_entity, get_entity_property +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 from canari.maltego.message import LinkDirection __author__ = 'Christophe Vandeplas' @@ -22,6 +22,7 @@ class AttributeInMISP(Transform): input_type = Unknown def do_transform(self, request, response, config): + response += check_update(config) maltego_misp_attribute = request.entity # skip MISP Events (value = int) try: @@ -69,6 +70,7 @@ class AttributeToEvent(Transform): input_type = Unknown def do_transform(self, request, response, config): + response += check_update(config) # skip some Entities skip = ['properties.mispevent'] for i in skip: diff --git a/src/MISP_maltego/transforms/common/util.py b/src/MISP_maltego/transforms/common/util.py index 58e95bb..970f971 100644 --- a/src/MISP_maltego/transforms/common/util.py +++ b/src/MISP_maltego/transforms/common/util.py @@ -1,60 +1,18 @@ from canari.maltego.entities import Hash, Domain, IPv4Address, URL, DNSName, AS, Website, NSRecord, PhoneNumber, EmailAddress, File, Person, Hashtag, Location, Company, Alias, Port, Twitter +from canari.maltego.message import Label, LinkStyle, MaltegoException, Bookmark, LinkDirection, UIMessage, UIMessageType +from distutils.version import StrictVersion from MISP_maltego.transforms.common.entities import MISPEvent, MISPObject, MISPGalaxy -from canari.maltego.message import Label, LinkStyle, MaltegoException, Bookmark, LinkDirection from pymisp import ExpandedPyMISP as PyMISP import json import os import os.path +import requests import tempfile import time # FIXME from galaxy 'to MISP Event' is confusing -# mapping_maltego_to_misp = { -# 'maltego.Hash': ['md5', 'sha1', 'sha256', 'sha224', 'sha384', 'sha512', 'sha512/224', 'sha512/256'], -# # 'maltego.Banner': [''], -# # 'maltego.WebTitle': [''], -# 'maltego.Domain': ['domain', 'hostname'], -# # 'maltego.Netblock': [''], -# # 'maltego.MXRecord': [''], -# 'maltego.IPv4Address': ['ip-src', 'ip-dst', 'ip'], -# 'maltego.URL': ['url', 'uri'], -# 'maltego.DNSName': ['domain', 'hostname'], -# 'maltego.AS': ['AS'], -# # 'maltego.UniqueIdentifier': [''], -# 'maltego.Website': ['domain', 'hostname'], -# 'maltego.NSRecord': ['domain', 'hostname'], -# # 'maltego.Document': [''], -# 'maltego.PhoneNumber': ['phone-number'], -# 'maltego.EmailAddress': ['email-src', 'email-dst'], -# # 'maltego.Image': [''], # TODO file image -# # 'maltego.Phrase': [''], -# 'maltego.File': ['filename'], -# # 'maltego.Person': [''], -# # 'maltego.Sentiment': [''], -# # 'maltego.Alias': [''], -# # 'maltego.GPS': [''], -# # 'maltego.CircularArea': [''], -# # 'maltego.NominatimLocation': [''], -# # 'maltego.Location': [''], -# # 'maltego.Device': [''], -# # 'maltego.affiliation.Flickr': [''], -# # 'maltego.FacebookObject': [''], -# # 'maltego.hashtag': [''], -# # 'maltego.affiliation.Twitter': [''], -# # 'maltego.affiliation.Facebook': [''], -# # 'maltego.Twit': [''], -# # 'maltego.Port': [''], -# # 'maltego.Service': [''], -# # 'maltego.BuiltWithTechnology': [''], -# } - -# mapping_misp_to_maltego = {} -# for key, vals in mapping_maltego_to_misp.items(): -# for val in vals: -# if val not in mapping_misp_to_maltego: -# mapping_misp_to_maltego[val] = [] -# mapping_misp_to_maltego[val].append(key) +__version__ = '1.3.4' mapping_misp_to_maltego = { 'AS': [AS], @@ -127,6 +85,40 @@ mapping_galaxy_icon = { 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) + + +def check_update(config): + # only raise the alert once a day/reboot to the user. + try: + if time.time() - os.path.getmtime(local_path_version) > 60 * 60 * 24: # check the timestamp of the file + recheck = True + else: + recheck = False + except Exception: # file does not exist, so check version + recheck = True + if not recheck: + return None + # remember we checked the version + from pathlib import Path + Path(local_path_version).touch() + # UIMessageType must be Fatal as otherwise it is not shown to the user. + if 'MISP_maltego.local.check_updates' not in config: + return UIMessage("'check_updates' parameter missing in '.canari/MISP_maltego.conf'. Please set 'check_updates = True/False'.", type=UIMessageType.Fatal) + if config['MISP_maltego.local.check_updates']: + # check the version + r = requests.get(update_url) + for l in r.text.splitlines(): + if 'version=' in l: + online_ver = l.strip().strip(',').split('=').pop().strip("'") + if StrictVersion(online_ver) > StrictVersion(__version__): + return UIMessage("A new version of MISP-Maltego is available. Use pip3 --upgrade MISP-maltego to upgrade.", type=UIMessageType.Fatal) + break + return None def get_misp_connection(config=None): @@ -427,7 +419,6 @@ def galaxycluster_to_entity(c, link_label=None, link_direction=LinkDirection.Inp # LATER this uses the galaxies from github as the MISP web UI does not fully support the Galaxies in the webui. # See https://github.com/MISP/MISP/issues/3801 galaxy_archive_url = 'https://github.com/MISP/misp-galaxy/archive/master.zip' -local_path_root = os.path.join(tempfile.gettempdir(), 'MISP-maltego') local_path_uuid_mapping = os.path.join(local_path_root, 'MISP_maltego_galaxy_mapping.json') local_path_clusters = os.path.join(local_path_root, 'misp-galaxy-master', 'clusters') galaxy_cluster_uuids = None @@ -441,13 +432,10 @@ def galaxy_update_local_copy(force=False): from zipfile import ZipFile # some aging and automatic re-downloading - if not os.path.exists(local_path_root): - os.mkdir(local_path_root) - force = True if not os.path.exists(local_path_uuid_mapping): force = True else: - # force update if cache is older thn 24 hours + # force update if cache is older than 24 hours if time.time() - os.path.getmtime(local_path_uuid_mapping) > 60 * 60 * 24: force = True diff --git a/src/MISP_maltego/transforms/eventtoattributes.py b/src/MISP_maltego/transforms/eventtoattributes.py index 23f2bfc..86d0192 100644 --- a/src/MISP_maltego/transforms/eventtoattributes.py +++ b/src/MISP_maltego/transforms/eventtoattributes.py @@ -2,7 +2,7 @@ from canari.maltego.entities import Hashtag from canari.maltego.transform import Transform # from canari.framework import EnableDebugWindow from MISP_maltego.transforms.common.entities import MISPEvent, MISPObject -from MISP_maltego.transforms.common.util import 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, 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 canari.maltego.message import LinkStyle @@ -35,6 +35,7 @@ class EventToTransform(Transform): 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) event_id = maltego_misp_event.id @@ -166,6 +167,7 @@ class ObjectToAttributes(Transform): description = 'Expands an Object to Attributes' def do_transform(self, request, response, config): + response += check_update(config) maltego_object = request.entity misp = get_misp_connection(config) event_json = misp.get_event(maltego_object.event_id) @@ -188,6 +190,7 @@ class ObjectToRelations(Transform): description = 'Expands an Object to Relations' def do_transform(self, request, response, config): + response += check_update(config) maltego_object = request.entity misp = get_misp_connection(config) event_json = misp.get_event(maltego_object.event_id) diff --git a/src/MISP_maltego/transforms/galaxytoevent.py b/src/MISP_maltego/transforms/galaxytoevent.py index e115971..e68c5f8 100644 --- a/src/MISP_maltego/transforms/galaxytoevent.py +++ b/src/MISP_maltego/transforms/galaxytoevent.py @@ -1,7 +1,7 @@ from canari.maltego.transform import Transform # from canari.framework import EnableDebugWindow from MISP_maltego.transforms.common.entities import MISPEvent, MISPGalaxy -from MISP_maltego.transforms.common.util import 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, get_misp_connection, galaxycluster_to_entity, get_galaxy_cluster, get_galaxies_relating, search_galaxy_cluster, mapping_galaxy_icon from canari.maltego.message import UIMessageType, UIMessage, LinkDirection @@ -34,6 +34,7 @@ class GalaxyToEvents(Transform): input_type = MISPGalaxy def do_transform(self, request, response, config): + response += check_update(config) maltego_misp_galaxy = request.entity misp = get_misp_connection(config) if maltego_misp_galaxy.tag_name: @@ -52,6 +53,7 @@ class GalaxyToRelations(Transform): input_type = MISPGalaxy def do_transform(self, request, response, config): + response += check_update(config) maltego_misp_galaxy = request.entity if maltego_misp_galaxy.uuid: