chg: [galaxies] new better icons set + better relations
|
@ -1,6 +1,8 @@
|
|||
# Quick start guide
|
||||
This is a Maltego MISP integration tool allowing you to view (read-only) data from a MISP instance.
|
||||
|
||||
It also allows browsing through the [MITRE ATT&CK](https://attack.mitre.org/) entities.
|
||||
|
||||
Currently supported MISP elements are : Event, Attribute, Object (incl relations), Tag, Taxonomy, Galaxy (incl relations).
|
||||
|
||||
Once installed you can start by creating a `MISPEvent` entity, then load the Machine `EventToAll` or the transform `EventToAttributes`.
|
||||
|
@ -28,4 +30,4 @@ This software is licensed under [GNU Affero General Public License version 3](ht
|
|||
|
||||
Note: Before being rewritten from scratch this project was maintained by Emmanuel Bouillon. The code is available in the `v1` branch.
|
||||
|
||||
The icons in the fontawesome folder are from https://fontawesome.com/ which are licensed SIL OFL 1.1
|
||||
The icons in the intelligence-icons folder are from [intelligence-icons](https://github.com/MISP/intelligence-icons) licensed CC-BY-SA - Françoise Penninckx, Brett Jordan
|
||||
|
|
2
setup.py
|
@ -5,7 +5,7 @@ from setuptools import setup, find_packages
|
|||
setup(
|
||||
name='MISP_maltego',
|
||||
author='Christophe Vandeplas',
|
||||
version='1.0',
|
||||
version='1.1',
|
||||
author_email='christophe@vandeplas.com',
|
||||
maintainer='Christophe Vandeplas',
|
||||
url='https://github.com/MISP/MISP-maltego',
|
||||
|
|
Before Width: | Height: | Size: 661 B |
Before Width: | Height: | Size: 650 B |
Before Width: | Height: | Size: 678 B |
Before Width: | Height: | Size: 646 B |
Before Width: | Height: | Size: 838 B |
Before Width: | Height: | Size: 873 B |
Before Width: | Height: | Size: 572 B |
Before Width: | Height: | Size: 946 B |
Before Width: | Height: | Size: 295 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 742 B |
Before Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 464 B |
Before Width: | Height: | Size: 309 B |
Before Width: | Height: | Size: 669 B |
Before Width: | Height: | Size: 874 B |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -100,6 +100,29 @@ mapping_misp_to_maltego = {
|
|||
# 'rekey_value': [Unknown]
|
||||
}
|
||||
|
||||
mapping_galaxy_icon = {
|
||||
# "android": "malware", # "android",
|
||||
"btc": "ransomware",
|
||||
"bug": "vulnerability",
|
||||
# "cart-arrow-down": "malware", #"tds",
|
||||
"chain": "course_of_action",
|
||||
"door-open": "backdoor",
|
||||
"eye": "malware",
|
||||
"gavel": "tool",
|
||||
# "globe": "cert-eu-govsector",
|
||||
# "industry": "sector",
|
||||
# "internet-explorer": "exploit-kit",
|
||||
"key": "stealer",
|
||||
"map": "attack_pattern",
|
||||
"optin-monster": "malware",
|
||||
# "shield": "malpedia",
|
||||
# "shield": "preventive-measure",
|
||||
"sitemap": "botnet",
|
||||
"usd": "malware", # "banker",
|
||||
# "user-secret": "mitre-intrusion-set",
|
||||
"user-secret": "threat_actor",
|
||||
}
|
||||
|
||||
tag_note_prefixes = ['tlp:', 'PAP:', 'de-vs:', 'euci:', 'fr-classif:', 'nato:']
|
||||
|
||||
misp_connection = None
|
||||
|
@ -346,7 +369,12 @@ def galaxycluster_to_entity(c, link_label=None):
|
|||
galaxy_cluster = get_galaxy_cluster(c['uuid'])
|
||||
icon_url = None
|
||||
if 'icon' in galaxy_cluster: # LATER further investigate if using icons locally is a good idea.
|
||||
icon_url = 'file://{}/{}.png'.format(os.path.join(os.getcwd(), 'MISP_maltego', 'resources', 'images', 'fontawesome'), galaxy_cluster['icon'])
|
||||
# map the 'icon' name from the cluster to the icon filename of the intelligence-icons repository
|
||||
try:
|
||||
icon_url = 'file://{}/{}.png'.format(os.path.join(os.getcwd(), 'MISP_maltego', 'resources', 'images', 'intelligence-icons'), mapping_galaxy_icon[galaxy_cluster['icon']])
|
||||
except Exception:
|
||||
# it's not in our mapping, just ignore and leave the default Galaxy icon
|
||||
pass
|
||||
if c['meta'].get('synonyms'):
|
||||
synonyms = ', '.join(c['meta']['synonyms'])
|
||||
else:
|
||||
|
@ -433,9 +461,26 @@ def galaxy_load_cluster_mapping():
|
|||
return cluster_uuids
|
||||
|
||||
|
||||
def get_galaxy_cluster(uuid):
|
||||
def get_galaxy_cluster(uuid=None, tag=None):
|
||||
global galaxy_cluster_uuids
|
||||
if not galaxy_cluster_uuids:
|
||||
galaxy_cluster_uuids = galaxy_load_cluster_mapping()
|
||||
|
||||
return galaxy_cluster_uuids.get(uuid)
|
||||
if uuid:
|
||||
return galaxy_cluster_uuids.get(uuid)
|
||||
if tag:
|
||||
for item in galaxy_cluster_uuids.values():
|
||||
if item['tag_name'] == tag:
|
||||
return item
|
||||
|
||||
|
||||
def get_galaxies_relating(uuid):
|
||||
global galaxy_cluster_uuids
|
||||
if not galaxy_cluster_uuids:
|
||||
galaxy_cluster_uuids = galaxy_load_cluster_mapping()
|
||||
|
||||
for item in galaxy_cluster_uuids.values():
|
||||
if 'related' in item:
|
||||
for related in item['related']:
|
||||
if related['dest-uuid'] == uuid:
|
||||
yield item
|
||||
|
|
|
@ -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
|
||||
from MISP_maltego.transforms.common.util import get_misp_connection, galaxycluster_to_entity, get_galaxy_cluster, get_galaxies_relating, mapping_galaxy_icon
|
||||
from canari.maltego.message import UIMessageType, UIMessage
|
||||
|
||||
|
||||
|
@ -49,15 +49,51 @@ class GalaxyToRelations(Transform):
|
|||
def do_transform(self, request, response, config):
|
||||
maltego_misp_galaxy = request.entity
|
||||
|
||||
# # FIXME if not found, send message to user to update, while noting local galaxies are not supported yet
|
||||
current_cluster = get_galaxy_cluster(maltego_misp_galaxy.uuid)
|
||||
if not current_cluster:
|
||||
response += UIMessage("Galaxy Cluster UUID not in local mapping. Please update local cache; or non-public UUID", type=UIMessageType.Inform)
|
||||
return response
|
||||
if maltego_misp_galaxy.uuid:
|
||||
current_cluster = get_galaxy_cluster(uuid=maltego_misp_galaxy.uuid)
|
||||
elif maltego_misp_galaxy.tag_name:
|
||||
current_cluster = get_galaxy_cluster(tag=maltego_misp_galaxy.tag_name)
|
||||
elif maltego_misp_galaxy.name:
|
||||
current_cluster = get_galaxy_cluster(tag=maltego_misp_galaxy.name)
|
||||
|
||||
if not current_cluster:
|
||||
response += UIMessage("Galaxy Cluster UUID not in local mapping. Please update local cache; non-public UUID are not supported yet.", type=UIMessageType.Inform)
|
||||
return response
|
||||
c = current_cluster
|
||||
# update existing object
|
||||
# import json
|
||||
# print(json.dumps(c, sort_keys=True, indent=2))
|
||||
# return response
|
||||
galaxy_cluster = get_galaxy_cluster(c['uuid'])
|
||||
icon_url = None
|
||||
import os
|
||||
if 'icon' in galaxy_cluster: # LATER further investigate if using icons locally is a good idea.
|
||||
# map the 'icon' name from the cluster to the icon filename of the intelligence-icons repository
|
||||
try:
|
||||
icon_url = 'file://{}/{}.png'.format(os.path.join(os.getcwd(), 'MISP_maltego', 'resources', 'images', 'intelligence-icons'), mapping_galaxy_icon[galaxy_cluster['icon']])
|
||||
except Exception:
|
||||
# it's not in our mapping, just ignore and leave the default Galaxy icon
|
||||
pass
|
||||
if c['meta'].get('synonyms'):
|
||||
synonyms = ', '.join(c['meta']['synonyms'])
|
||||
else:
|
||||
synonyms = ''
|
||||
request.entity.name = '{}\n{}'.format(c['type'], c['value'])
|
||||
request.entity.uuid = c['uuid']
|
||||
request.entity.description = c.get('description')
|
||||
request.entity.cluster_type = c.get('type')
|
||||
request.entity.cluster_value = c.get('value')
|
||||
request.entity.synonyms = synonyms
|
||||
request.entity.tag_name = c['tag_name']
|
||||
request.entity.icon_url = icon_url
|
||||
# response += request.entity
|
||||
# find related objects
|
||||
if 'related' in current_cluster:
|
||||
for related in current_cluster['related']:
|
||||
related_cluster = get_galaxy_cluster(related['dest-uuid'])
|
||||
if related_cluster:
|
||||
response += galaxycluster_to_entity(related_cluster, link_label=related['type'])
|
||||
# find objects that are relating to this one
|
||||
# for related in get_galaxies_relating(current_cluster['uuid']):
|
||||
# response += galaxycluster_to_entity(related, link_label="FIXME opposite of ".format(related['type'])) # FIXME link_label should be opposite
|
||||
return response
|
||||
|
|