From 2722cc3975fea2c6fb9320418ecd90d73542440a Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Tue, 5 Feb 2019 17:59:02 +0100 Subject: [PATCH 1/9] fix: [install] fixes #9 by preventing installation with python2 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index d31dee6..44e8a07 100755 --- a/setup.py +++ b/setup.py @@ -28,6 +28,7 @@ setup( package_data={ '': ['*.gif', '*.png', '*.conf', '*.mtz', '*.machine'] # list of resources }, + python_requires='>=3.5', install_requires=[ 'canari>=3.3.9,<4', 'PyMISP' From 0015cbb7f7aee33ffde0b9da3b620febf3517f3b Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Thu, 7 Feb 2019 14:02:55 +0100 Subject: [PATCH 2/9] chg: show error message if connection to MISP server fails --- src/MISP_maltego/transforms/common/util.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/MISP_maltego/transforms/common/util.py b/src/MISP_maltego/transforms/common/util.py index d22bc40..f56407c 100644 --- a/src/MISP_maltego/transforms/common/util.py +++ b/src/MISP_maltego/transforms/common/util.py @@ -1,6 +1,6 @@ from canari.maltego.entities import Unknown, Hash, Domain, IPv4Address, URL, DNSName, AS, Website, NSRecord, PhoneNumber, EmailAddress, File, Person, Hashtag, Location, Company, Alias, Port, Twitter from MISP_maltego.transforms.common.entities import MISPEvent, MISPObject, MISPGalaxy -from canari.maltego.message import UIMessageType, UIMessage, Label, LinkStyle +from canari.maltego.message import UIMessageType, UIMessage, Label, LinkStyle, MaltegoException from pymisp import PyMISP import json import os @@ -110,7 +110,7 @@ def get_misp_connection(config=None): if misp_connection: return misp_connection if not config: - raise Exception("ERROR: MISP connection not yet established, and config not provided as parameter.") + raise MaltegoException("ERROR: MISP connection not yet established, and config not provided as parameter.") if config['MISP_maltego.local.misp_verify'] in ['True', 'true', 1, 'yes', 'Yes']: misp_verify = True else: @@ -119,7 +119,10 @@ def get_misp_connection(config=None): misp_debug = True else: misp_debug = False - misp_connection = PyMISP(config['MISP_maltego.local.misp_url'], config['MISP_maltego.local.misp_key'], misp_verify, 'json', misp_debug) + try: + misp_connection = PyMISP(config['MISP_maltego.local.misp_url'], config['MISP_maltego.local.misp_key'], misp_verify, 'json', misp_debug) + except Exception: + raise MaltegoException("ERROR: Cannot connect to MISP server. Please verify your MISP_Maltego.conf settings") return misp_connection From d9ddb08387dcedfcfd06480c0dd4552a548b5640 Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Thu, 7 Feb 2019 14:03:30 +0100 Subject: [PATCH 3/9] fix: [tags] tags as notes for events - see issue #4 --- src/MISP_maltego/transforms/common/util.py | 10 ++++++++++ src/MISP_maltego/transforms/eventtoattributes.py | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/MISP_maltego/transforms/common/util.py b/src/MISP_maltego/transforms/common/util.py index f56407c..ec831d8 100644 --- a/src/MISP_maltego/transforms/common/util.py +++ b/src/MISP_maltego/transforms/common/util.py @@ -154,6 +154,9 @@ def attribute_to_entity(a, link_label=None, event_tags=None): # ignore all misp-galaxies if t['name'].startswith('misp-galaxy'): continue + # ignore all those we add as notes + if tag_matches_note_prefix(t['name']): + continue yield Hashtag(t['name']) notes = convert_tags_to_note(combined_tags) @@ -309,6 +312,13 @@ def convert_tags_to_note(tags): return '\n'.join(notes) +def tag_matches_note_prefix(tag): + for tag_note_prefix in tag_note_prefixes: + if tag.startswith(tag_note_prefix): + return True + return False + + def event_to_entity(e, link_style=LinkStyle.Normal): tags = [] if 'Tag' in e['Event']: diff --git a/src/MISP_maltego/transforms/eventtoattributes.py b/src/MISP_maltego/transforms/eventtoattributes.py index 886a513..f4401d2 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 +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, tag_matches_note_prefix from canari.maltego.message import LinkStyle import json @@ -33,6 +33,7 @@ class EventToAttributes(Transform): if not event_json.get('Event'): return response + response += event_to_entity(event_json) event_tags = [] if 'Tag' in event_json['Event']: for t in event_json['Event']['Tag']: @@ -40,6 +41,9 @@ class EventToAttributes(Transform): # ignore all misp-galaxies if t['name'].startswith('misp-galaxy'): continue + # ignore all those we add as notes + if tag_matches_note_prefix(t['name']): + continue response += Hashtag(t['name']) for g in event_json['Event']['Galaxy']: for c in g['GalaxyCluster']: From ccb1aa2f845e64f5bcf0ad681aac9cca52c59724 Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Thu, 7 Feb 2019 14:57:15 +0100 Subject: [PATCH 4/9] new: green bookmark #8 --- README.md | 4 --- doc/README.md | 16 +++++++--- doc/img/usecase3-bookmark.png | Bin 0 -> 10663 bytes .../transforms/attributetoevent.py | 18 +++++++---- src/MISP_maltego/transforms/common/util.py | 30 ++++++++++-------- 5 files changed, 38 insertions(+), 30 deletions(-) create mode 100644 doc/img/usecase3-bookmark.png diff --git a/README.md b/README.md index 60e3167..5740619 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,6 @@ Alternatively initiate a transform on an existing Maltego entity. The currently supported entities are: `AS`, `DNSName`, `Domain`, `EmailAddress`, `File`, `Hash`, `IPv4Address`, `NSRecord`, `Person`, `PhoneNumber`, `URL`, `Website` -Dependencies: -* [PyMISP](https://github.com/MISP/PyMISP) -* [Canari3](https://github.com/redcanari/canari3) - ## Installation and User Guide: Installation is fairly easy, just read the steps in the [documentation](https://github.com/MISP/MISP-maltego/blob/master/doc/README.md). diff --git a/doc/README.md b/doc/README.md index c2e874c..177cd04 100644 --- a/doc/README.md +++ b/doc/README.md @@ -36,7 +36,7 @@ In this use case we will be using already existing entities and will initiate a Example: * create an entity `domain` with the value `1dnscontrol.com`. * right click and choose *Local Transforms* > *MISP_maltego* > *Domain To Event* -![animated screenshot](https://github.com/MISP/MISP-maltego/blob/master/doc/img/usecase1-transform.gif) +![animated screenshot](https://raw.githubusercontent.com/MISP/MISP-maltego/master/doc/img/usecase1-transform.gif) * continue loading transforms on the *MISP Event* ## Transform from MISP Event ID @@ -45,14 +45,20 @@ While MISP already has a graphing capability we would like to use the power of M * One **manual** way is to right click and choose *Local Transforms* > *MISP_maltego* > *Event To Attributes* * Notice the event is transformed to *Attributes*, *Objects*, *Tags*, *Galaxies* and related *MISP Events* * You can now further transform on an *Object* > *Object To Attributes* and see the content of the object -![machine transforms](https://github.com/MISP/MISP-maltego/blob/master/doc/img/usecase2-manual.gif) +![machine transforms](https://raw.githubusercontent.com/MISP/MISP-maltego/master/doc/img/usecase2-manual.gif) * Alternatively you can also use the **Maltego Machine** to speed up things. * Click on the *MISP Event* and in the left menu choose *Event to All* in the *Machines* section. -![machine transforms](https://github.com/MISP/MISP-maltego/blob/master/doc/img/usecase2-machine-menu.png) +![machine transforms](https://raw.githubusercontent.com/MISP/MISP-maltego/master/doc/img/usecase2-machine-menu.png) * Notice that the whole event, objects and such will get expanded with data from your MISP instance. -![animated screenshot](https://github.com/MISP/MISP-maltego/blob/master/doc/img/usecase2-machine.gif) +![animated screenshot](https://raw.githubusercontent.com/MISP/MISP-maltego/master/doc/img/usecase2-machine.gif) * You can now further transform on any data. - + +## Which data is already in MISP? +If you use MISP as central database it can be quite convenient to know which data is present in MISP, and which data is not; especially after using a number of other transforms. +To permit this MISP-Maltego will always add a green bookmark to all the data that is present in MISP. +![green bookmark](https://raw.githubusercontent.com/MISP/MISP-maltego/master/doc/img/usecase3-bookmark.png) + + ## Transform from Galaxy TODO ## Visualise MITRE ATT&CK diff --git a/doc/img/usecase3-bookmark.png b/doc/img/usecase3-bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba814ad700e2f2c03c831091ddd475d0efb6455 GIT binary patch literal 10663 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 N002ovPDHLkV1hWS0@wfm literal 0 HcmV?d00001 diff --git a/src/MISP_maltego/transforms/attributetoevent.py b/src/MISP_maltego/transforms/attributetoevent.py index c9dbb4f..436870f 100644 --- a/src/MISP_maltego/transforms/attributetoevent.py +++ b/src/MISP_maltego/transforms/attributetoevent.py @@ -1,7 +1,7 @@ from canari.maltego.entities import Hash, Domain, IPv4Address, URL, DNSName, AS, Website, NSRecord, PhoneNumber, EmailAddress, File, Hashtag, Company, Alias, Twitter from canari.maltego.transform import Transform +from canari.maltego.message import Bookmark # from canari.framework import EnableDebugWindow -from MISP_maltego.transforms.common.entities import MISPEvent from MISP_maltego.transforms.common.util import get_misp_connection, event_to_entity __author__ = 'Christophe Vandeplas' @@ -23,10 +23,14 @@ class AttributeToEvent(Transform): def do_transform(self, request, response, config): maltego_misp_attribute = request.entity misp = get_misp_connection(config) - # misp. events_json = misp.search(controller='events', values=maltego_misp_attribute.value, withAttachments=False) + in_misp = False for e in events_json['response']: + in_misp = True response += event_to_entity(e) + if in_misp: + request.entity.bookmark = Bookmark.Green + response += request.entity return response def on_terminate(self): @@ -44,22 +48,22 @@ class DomainToEvent(AttributeToEvent): class IPv4AddressToEvent(AttributeToEvent): - display_name = 'IPv4AddressToEvent' + display_name = 'IPv4Address To Event' input_type = IPv4Address class URLToEvent(AttributeToEvent): - display_name = 'URLToEvent' + display_name = 'URL To Event' input_type = URL class DNSNameToEvent(AttributeToEvent): - display_name = 'DNSNameToEvent' + display_name = 'DNSName To Event' input_type = DNSName class ASToEvent(AttributeToEvent): - display_name = 'ASToEvent' + display_name = 'AS To Event' input_type = AS @@ -68,7 +72,7 @@ class WebsiteToEvent(AttributeToEvent): class NSRecordToEvent(AttributeToEvent): - display_name = 'NSRecordToEvent' + display_name = 'NSRecord To Event' input_type = NSRecord diff --git a/src/MISP_maltego/transforms/common/util.py b/src/MISP_maltego/transforms/common/util.py index ec831d8..e63dcc7 100644 --- a/src/MISP_maltego/transforms/common/util.py +++ b/src/MISP_maltego/transforms/common/util.py @@ -1,6 +1,6 @@ from canari.maltego.entities import Unknown, Hash, Domain, IPv4Address, URL, DNSName, AS, Website, NSRecord, PhoneNumber, EmailAddress, File, Person, Hashtag, Location, Company, Alias, Port, Twitter from MISP_maltego.transforms.common.entities import MISPEvent, MISPObject, MISPGalaxy -from canari.maltego.message import UIMessageType, UIMessage, Label, LinkStyle, MaltegoException +from canari.maltego.message import UIMessageType, UIMessage, Label, LinkStyle, MaltegoException, Bookmark from pymisp import PyMISP import json import os @@ -128,9 +128,9 @@ def get_misp_connection(config=None): 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 + return entity_obj(v, _type=t, bookmark=Bookmark.Green, **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 - return entity_obj(v, **kwargs) + return entity_obj(v, bookmark=Bookmark.Green, **kwargs) def attribute_to_entity(a, link_label=None, event_tags=None): @@ -157,19 +157,19 @@ def attribute_to_entity(a, link_label=None, event_tags=None): # ignore all those we add as notes if tag_matches_note_prefix(t['name']): continue - yield Hashtag(t['name']) + yield Hashtag(t['name'], bookmark=Bookmark.Green) notes = convert_tags_to_note(combined_tags) # special cases if a['type'] in ('url', 'uri'): - yield(URL(url=a['value'], link_label=link_label, notes=notes)) + yield(URL(url=a['value'], link_label=link_label, notes=notes, bookmark=Bookmark.Green)) return # attribute is from an object, and a relation gives better understanding of the type of attribute if a.get('object_relation') and mapping_misp_to_maltego.get(a['object_relation']): entity_obj = mapping_misp_to_maltego[a['object_relation']][0] - yield entity_obj(a['value'], labels=[Label('comment', a.get('comment'))], link_label=link_label, notes=notes) + yield entity_obj(a['value'], labels=[Label('comment', a.get('comment'))], link_label=link_label, notes=notes, bookmark=Bookmark.Green) # combined attributes elif '|' in a['type']: @@ -180,7 +180,7 @@ def attribute_to_entity(a, link_label=None, event_tags=None): labels = [Label('comment', a.get('comment'))] if entity_obj == File: labels.append(Label('hash', v_2)) - yield entity_obj_to_entity(entity_obj, v_1, t_1, labels=labels, link_label=link_label, notes=notes) # LATER change the comment to include the second part of the regkey + yield entity_obj_to_entity(entity_obj, v_1, t_1, labels=labels, link_label=link_label, notes=notes, bookmark=Bookmark.Green) # LATER change the comment to include the second part of the regkey else: yield UIMessage("Type {} of combined type {} not supported for attribute: {}".format(t_1, a['type'], a), type=UIMessageType.Inform) if t_2 in mapping_misp_to_maltego: @@ -188,18 +188,18 @@ def attribute_to_entity(a, link_label=None, event_tags=None): labels = [Label('comment', a.get('comment'))] if entity_obj == Hash: labels.append(Label('filename', v_1)) - yield entity_obj_to_entity(entity_obj, v_2, t_2, labels=labels, link_label=link_label, notes=notes) # LATER change the comment to include the first part of the regkey + yield entity_obj_to_entity(entity_obj, v_2, t_2, labels=labels, link_label=link_label, notes=notes, bookmark=Bookmark.Green) # LATER change the comment to include the first part of the regkey else: yield UIMessage("Type {} of combined type {} not supported for attribute: {}".format(t_2, a['type'], a), type=UIMessageType.Inform) # normal attributes elif a['type'] in mapping_misp_to_maltego: entity_obj = mapping_misp_to_maltego[a['type']][0] - yield entity_obj_to_entity(entity_obj, a['value'], a['type'], labels=[Label('comment', a.get('comment'))], link_label=link_label, notes=notes) + yield entity_obj_to_entity(entity_obj, a['value'], a['type'], labels=[Label('comment', a.get('comment'))], link_label=link_label, notes=notes, bookmark=Bookmark.Green) # not supported in our maltego mapping else: - yield Unknown(a['value'], type=a['type'], labels=[Label('comment', a.get('comment'))], link_label=link_label, notes=notes) + yield Unknown(a['value'], type=a['type'], labels=[Label('comment', a.get('comment'))], link_label=link_label, notes=notes, bookmark=Bookmark.Green) yield UIMessage("Type {} not fully supported for attribute: {}".format(a['type'], a), type=UIMessageType.Inform) # LATER : relationships from attributes - not yet supported by MISP yet, but there are references in the datamodel @@ -252,7 +252,8 @@ def object_to_entity(o, link_label=None): meta_category=o.get('meta_category'), description=o.get('description'), comment=o.get('comment'), - link_label=link_label + link_label=link_label, + bookmark=Bookmark.Green ) @@ -261,7 +262,7 @@ def object_to_attributes(o, e): if o['name'] == 'person': first_name = get_attribute_in_object(o, 'first-name', drop=True).get('value') last_name = get_attribute_in_object(o, 'last-name', drop=True).get('value') - yield entity_obj_to_entity(Person, ' '.join([first_name, last_name]).strip(), 'person', lastname=last_name, firstnames=first_name) + yield entity_obj_to_entity(Person, ' '.join([first_name, last_name]).strip(), 'person', lastname=last_name, firstnames=first_name, bookmark=Bookmark.Green) # process normal attributes for a in o['Attribute']: @@ -325,7 +326,7 @@ def event_to_entity(e, link_style=LinkStyle.Normal): for t in e['Event']['Tag']: tags.append(t['name']) notes = convert_tags_to_note(tags) - return MISPEvent(e['Event']['id'], uuid=e['Event']['uuid'], info=e['Event']['info'], link_style=link_style, notes=notes) + return MISPEvent(e['Event']['id'], uuid=e['Event']['uuid'], info=e['Event']['info'], link_style=link_style, notes=notes, bookmark=Bookmark.Green) def galaxycluster_to_entity(c, link_label=None): @@ -348,7 +349,8 @@ def galaxycluster_to_entity(c, link_label=None): synonyms=synonyms, tag_name=c['tag_name'], link_label=link_label, - icon_url=icon_url + icon_url=icon_url, + bookmark=Bookmark.Green ) From 35a2ed422cd2a5544a5e9e1b7658e50de2ad932d Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Thu, 7 Feb 2019 15:01:15 +0100 Subject: [PATCH 5/9] fix: better screenshot --- doc/img/usecase3-bookmark.png | Bin 10663 -> 19279 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/img/usecase3-bookmark.png b/doc/img/usecase3-bookmark.png index 0ba814ad700e2f2c03c831091ddd475d0efb6455..2dcaad922260844febfe6d26b7dbf82cd5f11226 100644 GIT binary patch literal 19279 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 literal 10663 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 N002ovPDHLkV1hWS0@wfm From cb485d63d4ee4ec7b7ea76cc0a6480cb0157c63f Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Fri, 8 Feb 2019 21:27:44 +0100 Subject: [PATCH 6/9] new: in MISP? machine fixes #8 --- .../resources/maltego/misp_inMISP.machine | 24 +++++ .../transforms/attributetoevent.py | 95 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 src/MISP_maltego/resources/maltego/misp_inMISP.machine diff --git a/src/MISP_maltego/resources/maltego/misp_inMISP.machine b/src/MISP_maltego/resources/maltego/misp_inMISP.machine new file mode 100644 index 0000000..cdf2790 --- /dev/null +++ b/src/MISP_maltego/resources/maltego/misp_inMISP.machine @@ -0,0 +1,24 @@ +machine("misp.inMISP", + displayName:"in MISP?", + author:"Christophe Vandeplas", + description: "Bookmarks in GREEN data that is in MISP") { + start { + paths { + run("MISP_maltego.AliasInMISP") + run("MISP_maltego.ASInMISP") + run("MISP_maltego.CompanyInMISP") + run("MISP_maltego.DNSNameInMISP") + run("MISP_maltego.DomainInMISP") + run("MISP_maltego.EmailAddressInMISP") + run("MISP_maltego.FileInMISP") + run("MISP_maltego.HashInMISP") + run("MISP_maltego.HashtagInMISP") + run("MISP_maltego.IPv4AddressInMISP") + run("MISP_maltego.NSRecordInMISP") + run("MISP_maltego.PhoneNumberInMISP") + run("MISP_maltego.TwitterInMISP") + run("MISP_maltego.URLInMISP") + run("MISP_maltego.WebsiteInMISP") + } + } +} diff --git a/src/MISP_maltego/transforms/attributetoevent.py b/src/MISP_maltego/transforms/attributetoevent.py index 436870f..beda4a4 100644 --- a/src/MISP_maltego/transforms/attributetoevent.py +++ b/src/MISP_maltego/transforms/attributetoevent.py @@ -15,6 +15,26 @@ __email__ = 'christophe@vandeplas.com' __status__ = 'Development' +# @EnableDebugWindow +class AttributeInMISP(Transform): + """This method puts a green bookmark on each of the Entities that are present in the MISP database""" + display_name = 'in MISP?' + input_type = None + + def do_transform(self, request, response, config): + maltego_misp_attribute = request.entity + misp = get_misp_connection(config) + events_json = misp.search(controller='events', values=maltego_misp_attribute.value, withAttachments=False) + in_misp = False + for e in events_json['response']: + in_misp = True + break + if in_misp: + request.entity.bookmark = Bookmark.Green + response += request.entity + return response + + # @EnableDebugWindow class AttributeToEvent(Transform): # The transform input entity type. @@ -102,3 +122,78 @@ class TwitterToEvent(AttributeToEvent): class CompanyToEvent(AttributeToEvent): input_type = Company + + +class HashInMISP(AttributeInMISP): + display_name = 'Hash in MISP?' + input_type = Hash + + +class DomainInMISP(AttributeInMISP): + display_name = 'Domain in MISP?' + input_type = Domain + + +class IPv4AddressInMISP(AttributeInMISP): + display_name = 'IPv4Address in MISP?' + input_type = IPv4Address + + +class URLInMISP(AttributeInMISP): + display_name = 'URL in MISP?' + input_type = URL + + +class DNSNameInMISP(AttributeInMISP): + display_name = 'DNSName in MISP?' + input_type = DNSName + + +class ASInMISP(AttributeInMISP): + display_name = 'AS in MISP?' + input_type = AS + + +class WebsiteInMISP(AttributeInMISP): + display_name = 'Website in MISP?' + input_type = Website + + +class NSRecordInMISP(AttributeInMISP): + display_name = 'NSRecord in MISP?' + input_type = NSRecord + + +class PhoneNumberInMISP(AttributeInMISP): + display_name = 'PhoneNumber in MISP?' + input_type = PhoneNumber + + +class EmailAddressInMISP(AttributeInMISP): + display_name = 'EmailAddress in MISP?' + input_type = EmailAddress + + +class FileInMISP(AttributeInMISP): + display_name = 'File in MISP?' + input_type = File + + +class HashtagInMISP(AttributeInMISP): + display_name = 'Hashtag in MISP?' + input_type = Hashtag + + +class AliasInMISP(AttributeInMISP): + display_name = 'Alias in MISP?' + input_type = Alias + + +class TwitterInMISP(AttributeInMISP): + display_name = 'Twitter in MISP?' + input_type = Twitter + + +class CompanyInMISP(AttributeInMISP): + display_name = 'Company in MISP?' + input_type = Company From 7b6796cda2aa64ca6a54a25bf7f4770831cdbcb0 Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Fri, 8 Feb 2019 22:41:33 +0100 Subject: [PATCH 7/9] chg: in MISP? as transform to all Entities this replaces the machine and gazillion of transforms --- .../resources/maltego/misp_inMISP.machine | 24 --- .../transforms/attributetoevent.py | 169 +++--------------- .../transforms/common/entities.py | 8 +- src/MISP_maltego/transforms/common/util.py | 25 ++- 4 files changed, 45 insertions(+), 181 deletions(-) delete mode 100644 src/MISP_maltego/resources/maltego/misp_inMISP.machine diff --git a/src/MISP_maltego/resources/maltego/misp_inMISP.machine b/src/MISP_maltego/resources/maltego/misp_inMISP.machine deleted file mode 100644 index cdf2790..0000000 --- a/src/MISP_maltego/resources/maltego/misp_inMISP.machine +++ /dev/null @@ -1,24 +0,0 @@ -machine("misp.inMISP", - displayName:"in MISP?", - author:"Christophe Vandeplas", - description: "Bookmarks in GREEN data that is in MISP") { - start { - paths { - run("MISP_maltego.AliasInMISP") - run("MISP_maltego.ASInMISP") - run("MISP_maltego.CompanyInMISP") - run("MISP_maltego.DNSNameInMISP") - run("MISP_maltego.DomainInMISP") - run("MISP_maltego.EmailAddressInMISP") - run("MISP_maltego.FileInMISP") - run("MISP_maltego.HashInMISP") - run("MISP_maltego.HashtagInMISP") - run("MISP_maltego.IPv4AddressInMISP") - run("MISP_maltego.NSRecordInMISP") - run("MISP_maltego.PhoneNumberInMISP") - run("MISP_maltego.TwitterInMISP") - run("MISP_maltego.URLInMISP") - run("MISP_maltego.WebsiteInMISP") - } - } -} diff --git a/src/MISP_maltego/transforms/attributetoevent.py b/src/MISP_maltego/transforms/attributetoevent.py index beda4a4..86422ff 100644 --- a/src/MISP_maltego/transforms/attributetoevent.py +++ b/src/MISP_maltego/transforms/attributetoevent.py @@ -2,7 +2,8 @@ from canari.maltego.entities import Hash, Domain, IPv4Address, URL, DNSName, AS, from canari.maltego.transform import Transform from canari.maltego.message import Bookmark # from canari.framework import EnableDebugWindow -from MISP_maltego.transforms.common.util import get_misp_connection, event_to_entity +from MISP_maltego.transforms.common.util import get_misp_connection, event_to_entity, get_attribute_in_event, attribute_to_entity +from MISP_maltego.transforms.common.entities import Unknown __author__ = 'Christophe Vandeplas' __copyright__ = 'Copyright 2018, MISP_maltego Project' @@ -17,9 +18,9 @@ __status__ = 'Development' # @EnableDebugWindow class AttributeInMISP(Transform): - """This method puts a green bookmark on each of the Entities that are present in the MISP database""" + """Green bookmark if known in MISP""" display_name = 'in MISP?' - input_type = None + input_type = Unknown def do_transform(self, request, response, config): maltego_misp_attribute = request.entity @@ -29,16 +30,21 @@ class AttributeInMISP(Transform): for e in events_json['response']: in_misp = True break + # find the object again, and bookmark it green + # we need to do really rebuild the Entity from scratch as request.entity is of type Unknown if in_misp: - request.entity.bookmark = Bookmark.Green - response += request.entity + for e in events_json['response']: + attr = get_attribute_in_event(e, maltego_misp_attribute.value) + if attr: + for item in attribute_to_entity(attr, only_self=True): + response += item return response # @EnableDebugWindow class AttributeToEvent(Transform): - # The transform input entity type. - input_type = None + display_name = 'to MISP Event' + input_type = Unknown def do_transform(self, request, response, config): maltego_misp_attribute = request.entity @@ -48,152 +54,17 @@ class AttributeToEvent(Transform): for e in events_json['response']: in_misp = True response += event_to_entity(e) + # find the object again, and bookmark it green + # we need to do really rebuild the Entity from scratch as request.entity is of type Unknown if in_misp: - request.entity.bookmark = Bookmark.Green - response += request.entity + for e in events_json['response']: + attr = get_attribute_in_event(e, maltego_misp_attribute.value) + if attr: + for item in attribute_to_entity(attr, only_self=True): + response += item return response def on_terminate(self): """This method gets called when transform execution is prematurely terminated. It is only applicable for local transforms. It can be excluded if you don't need it.""" pass - - -class HashToEvent(AttributeToEvent): - input_type = Hash - - -class DomainToEvent(AttributeToEvent): - input_type = Domain - - -class IPv4AddressToEvent(AttributeToEvent): - display_name = 'IPv4Address To Event' - input_type = IPv4Address - - -class URLToEvent(AttributeToEvent): - display_name = 'URL To Event' - input_type = URL - - -class DNSNameToEvent(AttributeToEvent): - display_name = 'DNSName To Event' - input_type = DNSName - - -class ASToEvent(AttributeToEvent): - display_name = 'AS To Event' - input_type = AS - - -class WebsiteToEvent(AttributeToEvent): - input_type = Website - - -class NSRecordToEvent(AttributeToEvent): - display_name = 'NSRecord To Event' - input_type = NSRecord - - -class PhoneNumberToEvent(AttributeToEvent): - input_type = PhoneNumber - - -class EmailAddressToEvent(AttributeToEvent): - input_type = EmailAddress - - -class FileToEvent(AttributeToEvent): - input_type = File - - -class HashtagToEvent(AttributeToEvent): - input_type = Hashtag - - -class AliasToEvent(AttributeToEvent): - input_type = Alias - - -class TwitterToEvent(AttributeToEvent): - input_type = Twitter - - -class CompanyToEvent(AttributeToEvent): - input_type = Company - - -class HashInMISP(AttributeInMISP): - display_name = 'Hash in MISP?' - input_type = Hash - - -class DomainInMISP(AttributeInMISP): - display_name = 'Domain in MISP?' - input_type = Domain - - -class IPv4AddressInMISP(AttributeInMISP): - display_name = 'IPv4Address in MISP?' - input_type = IPv4Address - - -class URLInMISP(AttributeInMISP): - display_name = 'URL in MISP?' - input_type = URL - - -class DNSNameInMISP(AttributeInMISP): - display_name = 'DNSName in MISP?' - input_type = DNSName - - -class ASInMISP(AttributeInMISP): - display_name = 'AS in MISP?' - input_type = AS - - -class WebsiteInMISP(AttributeInMISP): - display_name = 'Website in MISP?' - input_type = Website - - -class NSRecordInMISP(AttributeInMISP): - display_name = 'NSRecord in MISP?' - input_type = NSRecord - - -class PhoneNumberInMISP(AttributeInMISP): - display_name = 'PhoneNumber in MISP?' - input_type = PhoneNumber - - -class EmailAddressInMISP(AttributeInMISP): - display_name = 'EmailAddress in MISP?' - input_type = EmailAddress - - -class FileInMISP(AttributeInMISP): - display_name = 'File in MISP?' - input_type = File - - -class HashtagInMISP(AttributeInMISP): - display_name = 'Hashtag in MISP?' - input_type = Hashtag - - -class AliasInMISP(AttributeInMISP): - display_name = 'Alias in MISP?' - input_type = Alias - - -class TwitterInMISP(AttributeInMISP): - display_name = 'Twitter in MISP?' - input_type = Twitter - - -class CompanyInMISP(AttributeInMISP): - display_name = 'Company in MISP?' - input_type = Company diff --git a/src/MISP_maltego/transforms/common/entities.py b/src/MISP_maltego/transforms/common/entities.py index 3f75fb5..c32f89d 100644 --- a/src/MISP_maltego/transforms/common/entities.py +++ b/src/MISP_maltego/transforms/common/entities.py @@ -13,10 +13,16 @@ __status__ = 'Development' __all__ = [ 'MISPEvent', 'MISPObject', - 'MISPGalaxy' + 'MISPGalaxy', + 'Unknown' ] +class Unknown(Entity): + _category_ = 'Unknown' + _namespace_ = 'maltego' + + class MISPEvent(Entity): _category_ = 'MISP' _namespace_ = 'misp' diff --git a/src/MISP_maltego/transforms/common/util.py b/src/MISP_maltego/transforms/common/util.py index e63dcc7..703af50 100644 --- a/src/MISP_maltego/transforms/common/util.py +++ b/src/MISP_maltego/transforms/common/util.py @@ -1,5 +1,5 @@ -from canari.maltego.entities import Unknown, Hash, Domain, IPv4Address, URL, DNSName, AS, Website, NSRecord, PhoneNumber, EmailAddress, File, Person, Hashtag, Location, Company, Alias, Port, Twitter -from MISP_maltego.transforms.common.entities import MISPEvent, MISPObject, MISPGalaxy +from canari.maltego.entities import Hash, Domain, IPv4Address, URL, DNSName, AS, Website, NSRecord, PhoneNumber, EmailAddress, File, Person, Hashtag, Location, Company, Alias, Port, Twitter +from MISP_maltego.transforms.common.entities import MISPEvent, MISPObject, MISPGalaxy, Unknown from canari.maltego.message import UIMessageType, UIMessage, Label, LinkStyle, MaltegoException, Bookmark from pymisp import PyMISP import json @@ -128,12 +128,12 @@ def get_misp_connection(config=None): def entity_obj_to_entity(entity_obj, v, t, **kwargs): if entity_obj == Hash: - return entity_obj(v, _type=t, bookmark=Bookmark.Green, **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 + 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 - return entity_obj(v, bookmark=Bookmark.Green, **kwargs) + return entity_obj(v, **kwargs) -def attribute_to_entity(a, link_label=None, event_tags=None): +def attribute_to_entity(a, link_label=None, event_tags=None, only_self=False): # prepare some attributes to a better form a['data'] = None # empty the file content as we really don't need this here if a['type'] == 'malware-sample': @@ -142,13 +142,13 @@ def attribute_to_entity(a, link_label=None, event_tags=None): a['type'] = 'regkey' combined_tags = event_tags - if 'Galaxy' in a: + if 'Galaxy' in a and not only_self: for g in a['Galaxy']: for c in g['GalaxyCluster']: yield galaxycluster_to_entity(c) # TODO today the tag is attached to the event, not the attribute, this is something we want to fix soon. - if 'Tag' in a: + if 'Tag' in a and not only_self: for t in a['Tag']: combined_tags.append(t['name']) # ignore all misp-galaxies @@ -302,6 +302,17 @@ def get_attribute_in_object(o, attribute_type, drop=False): return found_attribute +def get_attribute_in_event(e, attribute_value): + for a in e['Event']["Attribute"]: + if a['value'] == attribute_value: + return a + for o in e['Event']['Object']: + for a in o['Attribute']: + if a['value'] == attribute_value: + return a + return None + + def convert_tags_to_note(tags): if not tags: return None From 521e2cd38a6eaa89ab710edef5e2965e570cb3e8 Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Sat, 9 Feb 2019 07:46:46 +0100 Subject: [PATCH 8/9] chg: [relations] Favor machines for Event relations --- .../maltego/misp_MISPEventToAll.machine | 31 ++++++++++++------- .../transforms/attributetoevent.py | 16 ++++++++-- .../transforms/eventtoattributes.py | 6 ++-- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/MISP_maltego/resources/maltego/misp_MISPEventToAll.machine b/src/MISP_maltego/resources/maltego/misp_MISPEventToAll.machine index 30b7167..fcc10b1 100644 --- a/src/MISP_maltego/resources/maltego/misp_MISPEventToAll.machine +++ b/src/MISP_maltego/resources/maltego/misp_MISPEventToAll.machine @@ -1,12 +1,19 @@ -machine("misp.MISPEventToAll", - displayName:"Event to All", - author:"Christophe Vandeplas", - description: "Automatically expands MISP Objects to their attributes") { - start { - run("MISP_maltego.EventToAttributes") - paths { - run("MISP_maltego.ObjectToAttributes") - run("MISP_maltego.GalaxyToRelations") - } - } -} +machine("misp.MISPEventToAll", + displayName:"Event to All", + author:"Christophe Vandeplas", + description: "Automatically expands MISP Objects to their attributes") { + start { + run("MISP_maltego.EventToAttributes") + run("MISP_maltego.AttributeToEvent") + paths { + path { + run("MISP_maltego.ObjectToAttributes") + run("MISP_maltego.AttributeToEvent") + } + path { + run("MISP_maltego.GalaxyToRelations") + } + } + + } +} diff --git a/src/MISP_maltego/transforms/attributetoevent.py b/src/MISP_maltego/transforms/attributetoevent.py index 86422ff..cea3db4 100644 --- a/src/MISP_maltego/transforms/attributetoevent.py +++ b/src/MISP_maltego/transforms/attributetoevent.py @@ -1,6 +1,4 @@ -from canari.maltego.entities import Hash, Domain, IPv4Address, URL, DNSName, AS, Website, NSRecord, PhoneNumber, EmailAddress, File, Hashtag, Company, Alias, Twitter from canari.maltego.transform import Transform -from canari.maltego.message import Bookmark # from canari.framework import EnableDebugWindow from MISP_maltego.transforms.common.util import get_misp_connection, event_to_entity, get_attribute_in_event, attribute_to_entity from MISP_maltego.transforms.common.entities import Unknown @@ -24,6 +22,13 @@ class AttributeInMISP(Transform): def do_transform(self, request, response, config): maltego_misp_attribute = request.entity + # skip MISP Events (value = int) + try: + int(maltego_misp_attribute.value) + return response + except Exception: + pass + misp = get_misp_connection(config) events_json = misp.search(controller='events', values=maltego_misp_attribute.value, withAttachments=False) in_misp = False @@ -48,6 +53,13 @@ class AttributeToEvent(Transform): def do_transform(self, request, response, config): maltego_misp_attribute = request.entity + # skip MISP Events (value = int) + try: + int(maltego_misp_attribute.value) + return response + except Exception: + pass + misp = get_misp_connection(config) events_json = misp.search(controller='events', values=maltego_misp_attribute.value, withAttachments=False) in_misp = False diff --git a/src/MISP_maltego/transforms/eventtoattributes.py b/src/MISP_maltego/transforms/eventtoattributes.py index f4401d2..2844935 100644 --- a/src/MISP_maltego/transforms/eventtoattributes.py +++ b/src/MISP_maltego/transforms/eventtoattributes.py @@ -24,7 +24,7 @@ class EventToAttributes(Transform): # The transform input entity type. input_type = MISPEvent - description = 'Expands an Event to Attributes, Tags, Galaxies and related events' + description = 'Expands an Event to Attributes, Tags, Galaxies' def do_transform(self, request, response, config): maltego_misp_event = request.entity @@ -49,8 +49,8 @@ class EventToAttributes(Transform): for c in g['GalaxyCluster']: response += galaxycluster_to_entity(c) - for e in event_json['Event']['RelatedEvent']: - response += event_to_entity(e, link_style=LinkStyle.DashDot) + # for e in event_json['Event']['RelatedEvent']: + # response += event_to_entity(e, link_style=LinkStyle.DashDot) for a in event_json['Event']["Attribute"]: for entity in attribute_to_entity(a, event_tags=event_tags): From d46f817e769cb4379b049fb979dcba40fb703d82 Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Tue, 12 Feb 2019 21:42:05 +0100 Subject: [PATCH 9/9] fix: [galaxies] add missing properties to the Galaxy Entity --- .../resources/maltego/entities.mtz | Bin 13559 -> 32210 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/MISP_maltego/resources/maltego/entities.mtz b/src/MISP_maltego/resources/maltego/entities.mtz index d52217b7c808e5f972626dd3e449c77af7d37048..5d82027b921ce2145bedad979170212f5640baa0 100644 GIT binary patch delta 20531 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 delta 1744 zcmZWp3p7*-7@oOijB19F@yK($ALB4lN-9~c(Rj^bcQM(fB6-BJ$P5~JY>A4w%6g2) z8Aat)qmE~r7@34rWQOQrsl1YBBzwp7vU~6O&bi;c-}(Rle*eASqb2yfzcj@`0)c}` zNlC$^Jr*3(rHz<(i8#CYoxG%p%zo@8oSD30BmefE(oALhM=T9g{(ueo(x~O&@f}@G z7hZVnGQjLj$Vhm5u)bfP!eYpln%0*p-A4`P-k@?cGtPDngc|=f%Bg-SQ01*~(%+@- zbP7?H+fDev6>PVA;Z-Nw$M4Z*Ec~{mm{QanP*QH)N{#U_7_1Aze+GQ) zhY$@4?uKiD83uo>I1Bo7YwayHIZIvfJ@R4KsQZgd|!pmzK+`_SCvF;8zrAQ^Rj zdLU=6J;x%y@QAQC`5+Ht;CY(-fkDhM8R@(xW8@i^8rL$sj$qWh=}>us?X%+8A%3QF zcWJ3%bHd4susX>^o!qfjVnz?qi1R@5YJq2WHY|(ng=AiiA}8|;0)8g|#8D20I2M`_M=oq|8od7NL2z`(1Dp^AD?fxk|U+%C^J?k`!TS zo$NCHbuAgICz`B?Q)t(iTMa=K&Y1IOs%ETxPsIsHjM`1rSG3<8#vakWgD49P@i{9b zJ*DdEGPBCV6CWu*3%_HtU`mZYqf|$Hym5QH{_)(5No#T!mz{gw|7@sJi2pm;A%RV- zf%hT#Oo3S@y~i~AC!ZzbjwHEw)=CbqtFofv@zhjmY%z0Y+54752X|24thSY#;9{`| zP@s*3hcqF4;V@XZ#M+GjtE(_&Mz}h;G!fAa(}dD~Po!h2ZJ(Tm@F4M6e4T&&M!u7g zzS_(n81(SwX>Y9$4I{mix*yhCQpVMTh=nN5hHj<7j$hiw7uRk2n}OT`q%NCVxR;nW zXIt5*Ki>U*h_Lw>u|t7uljP5uAzc6l@zXcLB5emETzP#5$^>AP>m38;R<`!x{3V@+ zP!pVyy<%aBqmSyWR(28P>95ngj}ya@w<(p|2I|e1kG5@qwLX36#iF$~sn?|VSmC)D zHnHJ!O7Wj0+tTF_OFT`c=Hno`Fhu)Jf)bTbsb-$1a8ib|l@}D*%D;#W@T<{?vxYmX zYq0~WoV;G=MfQe9Ih?R1w{rLGx)6NbKkM8B-@LPJ=}lv_(9?Jo-!#8sL|e+voS35b zDk39=L+;kvkdYq1S|cGJKLI9?k8J@>L~Q*CK_PZeKj|o=5|eZ}%~qJUXObESO7*Zj z`6i#1$ibuA)B3B->x5b9?=fKo9IAl!gN&WxRg2qMAw5guSG84euRYA?COzB=%U@B0 zk@UNZ_FzTxmd5SW62%P?(x}j__#!)E52{Muu!QKJ_Gw-cdE0I{g89$bx%$9Mwfi3! zkZSoY`{tb(Bl`{9(=5CvgGetqESWByBu4cCW5v$%E-9DdJEEp}Gf$}K)2 z8MQDK{*k@Ih8oI|nD#3x?byJT1LvfAHM!Tg*hRfCJ+)(PseYK>&Ai+k$K%Eh8zu@p zCrHn=gtLTdiA1@^vLCmZdpQ;9MnspYT<-KKt8e4_TTZ26^z1-Evu_?-+sKa|IhAr> zL*!%#mUmYda`NZ@Imy+RWCP-uD3I0Qjz|?rd}HP43B)Sn7Rb`pi?1YX5uX)o3Z6@_ z%N8p@5qm?fM2b~xiU1`C2XL@&dAS-?;6jv>hA5QCvBDP`P-Lk=P=|nkAU;~spKF3i zbSz#Z`~F`N$=82T!8XIegN$vfqVKIO5v{X2^F!;DCoRx68X@4;XbM$8Sz85AB?c{SM2JxauBd~gn9q$vAnvCPro@N~ m8FmTo7ouRWTnGwl3RxL~oiWNdq@?IB209y|K*Dbpv3~)v@V1Wt