2020-05-14 19:57:19 +02:00
|
|
|
from canari.maltego.entities import Unknown, Hashtag
|
2018-11-12 13:25:53 +01:00
|
|
|
from canari.maltego.transform import Transform
|
2020-05-14 19:57:19 +02:00
|
|
|
from MISP_maltego.transforms.common.entities import MISPGalaxy
|
2020-05-15 08:59:20 +02:00
|
|
|
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
|
2020-05-14 19:57:19 +02:00
|
|
|
from canari.maltego.message import LinkDirection, Bookmark
|
2018-11-12 13:25:53 +01:00
|
|
|
|
|
|
|
__author__ = 'Christophe Vandeplas'
|
|
|
|
__copyright__ = 'Copyright 2018, MISP_maltego Project'
|
|
|
|
__credits__ = []
|
|
|
|
|
|
|
|
__license__ = 'AGPLv3'
|
|
|
|
__version__ = '0.1'
|
|
|
|
__maintainer__ = 'Christophe Vandeplas'
|
|
|
|
__email__ = 'christophe@vandeplas.com'
|
|
|
|
__status__ = 'Development'
|
|
|
|
|
|
|
|
|
2020-05-14 19:57:19 +02:00
|
|
|
class SearchInMISP(Transform):
|
2020-05-15 09:29:05 +02:00
|
|
|
"""Use % at the front/end for wildcard search"""
|
2019-02-08 22:41:33 +01:00
|
|
|
input_type = Unknown
|
2020-05-14 19:57:19 +02:00
|
|
|
display_name = 'Search in MISP'
|
2020-05-15 09:29:05 +02:00
|
|
|
description = "Use % at the front/end for wildcard search"
|
2019-12-27 09:54:20 +01:00
|
|
|
remote = True
|
2019-02-08 21:27:44 +01:00
|
|
|
|
|
|
|
def do_transform(self, request, response, config):
|
2019-10-12 08:13:17 +02:00
|
|
|
response += check_update(config)
|
2020-05-14 19:57:19 +02:00
|
|
|
link_label = 'Search result'
|
|
|
|
|
|
|
|
if 'properties.mispevent' in request.entity.fields:
|
2020-05-15 08:59:20 +02:00
|
|
|
conn = MISPConnection(config, request.parameters)
|
2020-05-14 19:57:19 +02:00
|
|
|
# if event_id
|
|
|
|
try:
|
|
|
|
if request.entity.value == '0':
|
|
|
|
return response
|
|
|
|
eventid = int(request.entity.value)
|
2020-05-15 08:59:20 +02:00
|
|
|
events_json = conn.misp.search(controller='events', eventid=eventid, with_attachments=False)
|
2020-05-14 19:57:19 +02:00
|
|
|
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
|
2020-05-15 08:59:20 +02:00
|
|
|
events_json = conn.misp.search(controller='events', eventinfo=request.entity.value, with_attachments=False)
|
2020-05-14 19:57:19 +02:00
|
|
|
for e in events_json:
|
|
|
|
response += event_to_entity(e, link_label=link_label, link_direction=LinkDirection.OutputToInput)
|
2019-02-09 07:46:46 +01:00
|
|
|
return response
|
|
|
|
|
2020-05-14 19:57:19 +02:00
|
|
|
# From galaxy or Hashtag
|
2020-05-15 09:15:13 +02:00
|
|
|
if 'properties.mispgalaxy' in request.entity.fields or 'properties.temp' in request.entity.fields or 'twitter.hashtag' in request.entity.fields:
|
2020-05-14 19:57:19 +02:00
|
|
|
if request.entity.value == '-':
|
|
|
|
return response
|
|
|
|
# First search in galaxies
|
|
|
|
keyword = get_entity_property(request.entity, 'Temp')
|
|
|
|
if not keyword:
|
|
|
|
keyword = request.entity.value
|
|
|
|
# assume the user is searching for a cluster based on a substring.
|
|
|
|
# Search in the list for those that match and return galaxy entities'
|
|
|
|
potential_clusters = search_galaxy_cluster(keyword)
|
|
|
|
# LATER check if duplicates are possible
|
|
|
|
if potential_clusters:
|
|
|
|
for potential_cluster in potential_clusters:
|
|
|
|
new_entity = galaxycluster_to_entity(potential_cluster, link_label=link_label)
|
|
|
|
# LATER support the type_filter - unfortunately this is not possible, we need Canari to tell us the original entity type
|
|
|
|
if isinstance(new_entity, MISPGalaxy):
|
|
|
|
response += new_entity
|
|
|
|
|
|
|
|
# from Hashtag search also in tags
|
2020-05-15 09:15:13 +02:00
|
|
|
if 'properties.temp' in request.entity.fields or 'twitter.hashtag' in request.entity.fields:
|
2020-05-14 19:57:19 +02:00
|
|
|
keyword = get_entity_property(request.entity, 'Temp')
|
|
|
|
if not keyword:
|
|
|
|
keyword = request.entity.value
|
2020-05-15 08:59:20 +02:00
|
|
|
conn = MISPConnection(config, request.parameters)
|
|
|
|
result = conn.misp.direct_call('tags/search', {'name': keyword})
|
2020-05-14 19:57:19 +02:00
|
|
|
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
|
2020-05-15 08:59:20 +02:00
|
|
|
conn = MISPConnection(config, request.parameters)
|
|
|
|
events_json = conn.misp.search(controller='events', value=request.entity.value, with_attachments=False)
|
2019-02-08 22:41:33 +01:00
|
|
|
# we need to do really rebuild the Entity from scratch as request.entity is of type Unknown
|
2019-10-06 16:57:27 +02:00
|
|
|
for e in events_json:
|
2020-05-14 20:29:50 +02:00
|
|
|
# find the value as attribute
|
2020-05-14 19:57:19 +02:00
|
|
|
attr = get_attribute_in_event(e, request.entity.value, substring=True)
|
2019-10-06 16:57:27 +02:00
|
|
|
if attr:
|
|
|
|
for item in attribute_to_entity(attr, only_self=True):
|
|
|
|
response += item
|
2020-05-14 20:29:50 +02:00
|
|
|
# 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'):
|
2020-05-15 08:59:20 +02:00
|
|
|
response += conn.object_to_entity(o, link_label=link_label)
|
2020-05-14 20:29:50 +02:00
|
|
|
|
2019-02-08 21:27:44 +01:00
|
|
|
return response
|
|
|
|
|
2019-03-16 18:31:46 +01:00
|
|
|
# placeholder for https://github.com/MISP/MISP-maltego/issues/11
|
|
|
|
# waiting for support of CIDR search through the REST API
|
|
|
|
# @EnableDebugWindow
|
|
|
|
# class NetblockToAttributes(Transform):
|
|
|
|
# display_name = 'to MISP Attributes'
|
|
|
|
# input_type = Netblock
|
2019-12-27 09:54:20 +01:00
|
|
|
# remote = True
|
2019-03-16 18:31:46 +01:00
|
|
|
|
|
|
|
# def do_transform(self, request, response, config):
|
|
|
|
# maltego_misp_attribute = request.entity
|
2019-12-27 09:54:20 +01:00
|
|
|
# misp = get_misp_connection(config, request.parameters)
|
2019-03-16 18:31:46 +01:00
|
|
|
# import ipaddress
|
|
|
|
# ip_start, ip_end = maltego_misp_attribute.value.split('-')
|
2020-05-14 19:57:19 +02:00
|
|
|
# # LATER make this work with IPv4 and IPv6
|
2019-03-16 18:31:46 +01:00
|
|
|
# # automagically detect the different CIDRs
|
|
|
|
# cidrs = ipaddress.summarize_address_range(ipaddress.IPv4Address(ip_start), ipaddress.IPv4Address(ip_end))
|
|
|
|
# for cidr in cidrs:
|
|
|
|
# print(str(cidr))
|
2019-10-25 06:56:01 +02:00
|
|
|
# attr_json = misp.search(controller='attributes', value=str(cidr), with_attachments=False)
|
2019-03-16 18:31:46 +01:00
|
|
|
# print(attr_json)
|
|
|
|
# return response
|
|
|
|
|
|
|
|
|
2018-11-12 13:25:53 +01:00
|
|
|
class AttributeToEvent(Transform):
|
2019-02-08 22:41:33 +01:00
|
|
|
input_type = Unknown
|
2020-05-18 21:19:43 +02:00
|
|
|
display_name = 'To MISP Events'
|
2019-12-27 09:54:20 +01:00
|
|
|
remote = True
|
2018-11-12 13:25:53 +01:00
|
|
|
|
|
|
|
def do_transform(self, request, response, config):
|
2019-10-12 08:13:17 +02:00
|
|
|
response += check_update(config)
|
2019-03-26 21:12:02 +01:00
|
|
|
# skip some Entities
|
2019-05-24 16:54:34 +02:00
|
|
|
skip = ['properties.mispevent']
|
2019-03-26 21:12:02 +01:00
|
|
|
for i in skip:
|
|
|
|
if i in request.entity.fields:
|
|
|
|
return response
|
|
|
|
|
2019-03-16 18:31:46 +01:00
|
|
|
if 'ipv4-range' in request.entity.fields:
|
|
|
|
# placeholder for https://github.com/MISP/MISP-maltego/issues/11
|
|
|
|
pass
|
2019-02-09 07:46:46 +01:00
|
|
|
|
2020-05-15 08:59:20 +02:00
|
|
|
conn = MISPConnection(config, request.parameters)
|
2019-05-24 16:54:34 +02:00
|
|
|
# from Galaxy
|
2019-03-26 21:12:02 +01:00
|
|
|
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
|
2020-05-15 08:59:20 +02:00
|
|
|
events_json = conn.misp.search(controller='events', tags=tag_name, with_attachments=False)
|
2019-10-06 16:57:27 +02:00
|
|
|
for e in events_json:
|
|
|
|
response += event_to_entity(e, link_direction=LinkDirection.OutputToInput)
|
|
|
|
return response
|
2019-05-24 16:54:34 +02:00
|
|
|
# from Object
|
|
|
|
elif 'properties.mispobject' in request.entity.fields:
|
|
|
|
if request.entity.fields.get('event_id'):
|
2020-05-15 08:59:20 +02:00
|
|
|
events_json = conn.misp.search(controller='events', eventid=request.entity.fields.get('event_id').value, with_attachments=False)
|
2019-10-06 16:57:27 +02:00
|
|
|
for e in events_json:
|
2019-05-24 16:54:34 +02:00
|
|
|
response += event_to_entity(e, link_direction=LinkDirection.OutputToInput)
|
|
|
|
return response
|
|
|
|
else:
|
|
|
|
return response
|
2020-04-01 20:38:43 +02:00
|
|
|
# from Hashtag
|
2020-05-15 09:15:13 +02:00
|
|
|
elif 'properties.temp' in request.entity.fields or 'twitter.hashtag' in request.entity.fields:
|
2020-04-01 20:38:43 +02:00
|
|
|
tag_name = get_entity_property(request.entity, 'Temp')
|
|
|
|
if not tag_name:
|
|
|
|
tag_name = request.entity.value
|
2020-05-15 09:15:13 +02:00
|
|
|
events_json = conn.misp.search_index(tags=tag_name)
|
2020-04-01 20:38:43 +02:00
|
|
|
for e in events_json:
|
2020-05-15 09:15:13 +02:00
|
|
|
response += event_to_entity({'Event': e}, link_direction=LinkDirection.OutputToInput)
|
2020-04-01 20:38:43 +02:00
|
|
|
return response
|
2019-05-24 16:54:34 +02:00
|
|
|
# standard Entities (normal attributes)
|
2019-03-26 21:12:02 +01:00
|
|
|
else:
|
2020-05-15 08:59:20 +02:00
|
|
|
events_json = conn.misp.search(controller='events', value=request.entity.value, with_attachments=False)
|
2019-04-30 22:48:29 +02:00
|
|
|
|
|
|
|
# return the MISPEvent or MISPObject of the attribute
|
2019-10-06 16:57:27 +02:00
|
|
|
for e in events_json:
|
2019-04-30 22:48:29 +02:00
|
|
|
# find the value as attribute
|
|
|
|
attr = get_attribute_in_event(e, request.entity.value)
|
|
|
|
if attr:
|
2019-05-24 16:17:11 +02:00
|
|
|
response += event_to_entity(e, link_direction=LinkDirection.OutputToInput)
|
2019-04-30 22:48:29 +02:00
|
|
|
# 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'):
|
2020-05-15 08:59:20 +02:00
|
|
|
response += conn.object_to_entity(o, link_direction=LinkDirection.OutputToInput)
|
2019-04-30 22:48:29 +02:00
|
|
|
|
2018-11-12 13:25:53 +01:00
|
|
|
return response
|