mirror of https://github.com/MISP/MISP-maltego
parent
279f5418d6
commit
620690f745
|
@ -0,0 +1,174 @@
|
|||
#!/usr/bin/python
|
||||
#######################################################
|
||||
# Maltego Python Local Transform Helper #
|
||||
# Version 0.2 #
|
||||
# #
|
||||
# Local transform specification can be found at: #
|
||||
# http://ctas.paterva.com/view/Specification #
|
||||
# #
|
||||
# For more help and other local transforms #
|
||||
# try the forum or mail me: #
|
||||
# #
|
||||
# http://www.paterva.com/forum #
|
||||
# #
|
||||
# Andrew MacPherson [ andrew <<at>> Paterva.com ] #
|
||||
# #
|
||||
#######################################################
|
||||
import sys
|
||||
|
||||
def u2a_ascii(text):
|
||||
# takes care of "'ascii' codec can't encode character" errors
|
||||
return text.encode('unicode-escape')
|
||||
|
||||
class MaltegoEntity(object):
|
||||
value = "";
|
||||
weight = 100;
|
||||
displayInformation = None;
|
||||
additionalFields = [];
|
||||
iconURL = "";
|
||||
entityType = "Phrase"
|
||||
|
||||
def __init__(self,eT=None,v=None):
|
||||
if (eT is not None):
|
||||
self.entityType = eT;
|
||||
if (v is not None):
|
||||
self.value = sanitise(v);
|
||||
self.additionalFields = [];
|
||||
self.displayInformation = None;
|
||||
|
||||
def setType(self,eT=None):
|
||||
if (eT is not None):
|
||||
self.entityType = eT;
|
||||
|
||||
def setValue(self,eV=None):
|
||||
if (eV is not None):
|
||||
self.value = sanitise(eV);
|
||||
|
||||
def setWeight(self,w=None):
|
||||
if (w is not None):
|
||||
self.weight = w;
|
||||
|
||||
def setDisplayInformation(self,di=None):
|
||||
if (di is not None):
|
||||
self.displayInformation = di;
|
||||
|
||||
def addAdditionalFields(self,fieldName=None,displayName=None,matchingRule=False,value=None):
|
||||
self.additionalFields.append([sanitise(fieldName),sanitise(displayName),matchingRule,sanitise(value)]);
|
||||
|
||||
def setIconURL(self,iU=None):
|
||||
if (iU is not None):
|
||||
self.iconURL = iU;
|
||||
|
||||
def returnEntity(self):
|
||||
print "<Entity Type=\"" + str(self.entityType) + "\">";
|
||||
print "<Value>" + str(self.value) + "</Value>";
|
||||
print "<Weight>" + str(self.weight) + "</Weight>";
|
||||
if (self.displayInformation is not None):
|
||||
print "<DisplayInformation><Label Name=\"\" Type=\"text/html\"><![CDATA[" + str(self.displayInformation) + "]]></Label></DisplayInformation>";
|
||||
if (len(self.additionalFields) > 0):
|
||||
print "<AdditionalFields>";
|
||||
for i in range(len(self.additionalFields)):
|
||||
if (str(self.additionalFields[i][2]) <> "strict"):
|
||||
print "<Field Name=\"" + str(u2a_ascii(self.additionalFields[i][0])) + "\" DisplayName=\"" + str(u2a_ascii(self.additionalFields[i][1])) + "\">" + str(u2a_ascii(self.additionalFields[i][3])) + "</Field>";
|
||||
else:
|
||||
print "<Field MatchingRule=\"" + str(u2a_ascii(self.additionalFields[i][2])) + "\" Name=\"" + str(u2a_ascii(self.additionalFields[i][0])) + "\" DisplayName=\"" + str(u2a_ascii(self.additionalFields[i][1])) + "\">" + str(u2a_ascii(self.additionalFields[i][3])) + "</Field>";
|
||||
print "</AdditionalFields>";
|
||||
if (len(self.iconURL) > 0):
|
||||
print "<IconURL>" + self.iconURL + "</IconURL>";
|
||||
print "</Entity>";
|
||||
|
||||
class MaltegoTransform(object):
|
||||
entities = []
|
||||
exceptions = []
|
||||
UIMessages = []
|
||||
values = {};
|
||||
|
||||
def __init__(self):
|
||||
values = {};
|
||||
value = None;
|
||||
|
||||
def parseArguments(self,argv):
|
||||
if (argv[1] is not None):
|
||||
self.value = argv[1];
|
||||
|
||||
if (len(argv) > 2):
|
||||
if (argv[2] is not None):
|
||||
vars = argv[2].split('#');
|
||||
for x in range(0,len(vars)):
|
||||
vars_values = vars[x].split('=')
|
||||
if (len(vars_values) == 2):
|
||||
self.values[vars_values[0]] = vars_values[1];
|
||||
|
||||
def getValue(self):
|
||||
if (self.value is not None):
|
||||
return self.value;
|
||||
|
||||
def getVar(self,varName):
|
||||
if (varName in self.values.keys()):
|
||||
if (self.values[varName] is not None):
|
||||
return self.values[varName];
|
||||
|
||||
def addEntity(self,enType,enValue):
|
||||
me = MaltegoEntity(enType,enValue);
|
||||
self.addEntityToMessage(me);
|
||||
return self.entities[len(self.entities)-1];
|
||||
|
||||
def addEntityToMessage(self,maltegoEntity):
|
||||
self.entities.append(maltegoEntity);
|
||||
|
||||
def addUIMessage(self,message,messageType="Inform"):
|
||||
self.UIMessages.append([messageType,message]);
|
||||
|
||||
def addException(self,exceptionString):
|
||||
self.exceptions.append(exceptionString);
|
||||
|
||||
def throwExceptions(self):
|
||||
print "<MaltegoMessage>";
|
||||
print "<MaltegoTransformExceptionMessage>";
|
||||
print "<Exceptions>"
|
||||
|
||||
for i in range(len(self.exceptions)):
|
||||
print "<Exception>" + self.exceptions[i] + "</Exception>";
|
||||
print "</Exceptions>"
|
||||
print "</MaltegoTransformExceptionMessage>";
|
||||
print "</MaltegoMessage>";
|
||||
exit();
|
||||
|
||||
def returnOutput(self):
|
||||
print "<MaltegoMessage>";
|
||||
print "<MaltegoTransformResponseMessage>";
|
||||
|
||||
print "<Entities>"
|
||||
for i in range(len(self.entities)):
|
||||
self.entities[i].returnEntity();
|
||||
print "</Entities>"
|
||||
|
||||
print "<UIMessages>"
|
||||
for i in range(len(self.UIMessages)):
|
||||
print "<UIMessage MessageType=\"" + self.UIMessages[i][0] + "\">" + self.UIMessages[i][1] + "</UIMessage>";
|
||||
print "</UIMessages>"
|
||||
|
||||
print "</MaltegoTransformResponseMessage>";
|
||||
print "</MaltegoMessage>";
|
||||
|
||||
def writeSTDERR(self,msg):
|
||||
sys.stderr.write(str(msg));
|
||||
|
||||
def heartbeat(self):
|
||||
self.writeSTDERR("+");
|
||||
|
||||
def progress(self,percent):
|
||||
self.writeSTDERR("%" + str(percent));
|
||||
|
||||
def debug(self,msg):
|
||||
self.writeSTDERR("D:" + str(msg));
|
||||
|
||||
|
||||
|
||||
def sanitise(value):
|
||||
replace_these = ["&",">","<"];
|
||||
replace_with = ["&",">","<"];
|
||||
tempvalue = value;
|
||||
for i in range(0,len(replace_these)):
|
||||
tempvalue = tempvalue.replace(replace_these[i],replace_with[i]);
|
||||
return tempvalue;
|
|
@ -0,0 +1,29 @@
|
|||
MISP-Maltego
|
||||
|
||||
Set of Maltego transforms to interface with a MISP instance.
|
||||
|
||||
Prerequisites:
|
||||
- MISP instance API access
|
||||
- PyMISP
|
||||
|
||||
INSTALL:
|
||||
|
||||
- Edit misp_util.py and set BASE_URL and API_KEY variables with your MISP base URL and MISP API key.
|
||||
|
||||
- Create symbolic links to misp_domain2event.py and misp_event2domain.py
|
||||
$ for i in misp_email2event.py misp_email-subject2event.py misp_ip2event.py misp_hash2event.py ; do ln -s misp_domain2event.py $i; done
|
||||
$ for i in misp_event2email.py misp_event2email-subject.py misp_event2hash.py misp_event2ip.py ; do ln -s misp_event2domain.py $i; done
|
||||
|
||||
- Import transforms in Maltego as follows (for instance):
|
||||
misp_ip2event.py: [MISP] IP to Event / Returns MISPEvent entities containing the corresponding IP attribute
|
||||
misp_domain2event.py: [MISP] Domain to Event / Returns MISPEvent entities containing the corresponding Domain attribute
|
||||
misp_hash2event.py: [MISP] Hash to Event / Returns MISPEvent entities containing the corresponding Hash attribute
|
||||
misp_ip2event.py: [MISP] Email address to Event / Returns MISPEvent entities containing the corresponding Email address attribute
|
||||
misp_email-subject2event.py: [MISP] Email subject to Event / Returns MISPEvent entities containing the corresponding Email subject attribute
|
||||
misp_event2ip.py: [MISP] Event to IP attribute / Returns the IP attributes belonging to an event
|
||||
misp_event2domain.py: [MISP] Event to Domain attribute / Returns Domain attributes belonging to an event
|
||||
misp_event2hash.py: [MISP] Event to Hash attribute / Returns Hash attributes belonging to an event
|
||||
misp_event2email.py: [MISP] Event to Email address attribute / Returns Email address attributes belonging to an event
|
||||
misp_event2email-subject.py: [MISP] Event to Email subject attribute / Returns Email subject attributes belonging to an event
|
||||
misp_getEventInfo.py: [MISP] Get Event Info / Adorns the Event with Info as notes
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#############################################
|
||||
# MISP API Domain to Event
|
||||
#
|
||||
# Author: Emmanuel Bouillon
|
||||
# Email: emmanuel.bouillon.sec@gmail.com
|
||||
# Date: 24/11/2015
|
||||
#############################################
|
||||
import sys
|
||||
from misp_util import *
|
||||
from pymisp import PyMISP
|
||||
import json
|
||||
|
||||
attribute2filter = {
|
||||
'ip':'ip-src&&ip-dst', 'domain':'domain&&hostname',
|
||||
'hash':'md5&&sha1&&sha256&&malware-sample',
|
||||
'email':'email-src&&email-dst', 'email-subject': 'email-subject'
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
enValue = sys.argv[1]
|
||||
enType = sys.argv[0].split('_')[-1].split('2')[0] #misp_enType2event.py
|
||||
mt = MaltegoTransform()
|
||||
mt.addUIMessage("[INFO] " + enType + " to MISP Event")
|
||||
try:
|
||||
retrieveEvents(mt, attribute2filter[enType], enValue)
|
||||
except Exception as e:
|
||||
mt.addUIMessage("[Error] " + str(e))
|
||||
mt.returnOutput()
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#############################################
|
||||
# MISP API Domain to Event
|
||||
#
|
||||
# Author: Emmanuel Bouillon
|
||||
# Email: emmanuel.bouillon.sec@gmail.com
|
||||
# Date: 24/11/2015
|
||||
#############################################
|
||||
import sys
|
||||
from misp_util import *
|
||||
from pymisp import PyMISP
|
||||
import json
|
||||
|
||||
type2attribute = {'domain':('domain','hostname'), 'hostname':('hostname'), 'hash':('md5','sha1','sha256') , 'ip':('ip-src','ip-dst'), 'email':('email-src','email-dst'), 'email-subject': ('email-subject')}
|
||||
argType2enType = {'domain':'maltego.Domain', 'hostname':'maltego.Domain', 'hash':'maltego.Hash', 'ip':'maltego.IPv4Address', 'email':'maltego.EmailAddress', 'email-subject': 'maltego.Phrase'}
|
||||
filename_pipe_hash_type = ('filename|md5', 'filename|sha1', 'filename|sha256', 'malware-sample')
|
||||
|
||||
if __name__ == '__main__':
|
||||
event_id = sys.argv[1]
|
||||
argType = sys.argv[0].split('.')[0].split('2')[1] # misp_event2argType.py
|
||||
misp = init()
|
||||
try:
|
||||
event = misp.get_event(event_id)
|
||||
event_json = event.json()
|
||||
mt = MaltegoTransform()
|
||||
for attribute in event_json['Event']["Attribute"]:
|
||||
value = attribute["value"]
|
||||
aType = attribute["type"]
|
||||
if aType in type2attribute[argType]:
|
||||
if aType in filename_pipe_hash_type:
|
||||
h = value.split('|')[1].strip()
|
||||
me = MaltegoEntity(argType2enType[argType], h)
|
||||
mt.addEntityToMessage(me);
|
||||
else:
|
||||
me = MaltegoEntity(argType2enType[argType], value)
|
||||
mt.addEntityToMessage(me);
|
||||
except Exception as e:
|
||||
mt.addUIMessage("[ERROR] " + str(e))
|
||||
mt.returnOutput()
|
|
@ -0,0 +1,30 @@
|
|||
#############################################
|
||||
# MISP API Domain to Event
|
||||
#
|
||||
# Author: Emmanuel Bouillon
|
||||
# Email: emmanuel.bouillon.sec@gmail.com
|
||||
# Date: 24/11/2015
|
||||
#############################################
|
||||
import sys
|
||||
from misp_util import *
|
||||
from pymisp import PyMISP
|
||||
import json
|
||||
|
||||
if __name__ == '__main__':
|
||||
m = init()
|
||||
mt = MaltegoTransform()
|
||||
event_id = sys.argv[1]
|
||||
try:
|
||||
event = m.get_event(event_id)
|
||||
event_json = event.json()
|
||||
eid = event_json['Event']['id']
|
||||
einfo = event_json['Event']['info']
|
||||
eorgc = event_json['Event']['orgc']
|
||||
me = MaltegoEntity('maltego.MISPEvent',eid);
|
||||
me.addAdditionalFields('EventLink', 'EventLink', False, BASE_URL + '/events/view/' + eid )
|
||||
me.addAdditionalFields('Org', 'Org', False, eorgc)
|
||||
me.addAdditionalFields('notes#', 'notes', False, eorgc + ": " + einfo)
|
||||
mt.addEntityToMessage(me);
|
||||
except Exception as e:
|
||||
mt.addUIMessage("[ERROR] " + str(e))
|
||||
mt.returnOutput()
|
|
@ -0,0 +1,37 @@
|
|||
#############################################
|
||||
# MISP API miscellaneous functions.
|
||||
#
|
||||
# Author: Emmanuel Bouillon
|
||||
# Email: emmanuel.bouillon.sec@gmail.com
|
||||
# Date: 24/11/2015
|
||||
#############################################
|
||||
|
||||
# MISP BASE URL
|
||||
BASE_URL = '<MISP_BASE_URL>'
|
||||
# API KEY
|
||||
API_KEY = '<YOUR_API_KEY>'
|
||||
# MISP_VERIFYCERT
|
||||
MISP_VERIFYCERT = True
|
||||
# pyMISP DEBUG
|
||||
MISP_DEBUG = False
|
||||
|
||||
from pymisp import PyMISP
|
||||
from MaltegoTransform import *
|
||||
|
||||
def init():
|
||||
return PyMISP(BASE_URL, API_KEY, MISP_VERIFYCERT, 'json', MISP_DEBUG)
|
||||
|
||||
def retrieveEvents(mt, enFilter, enValue):
|
||||
misp = init()
|
||||
result = misp.search(values = enValue, type_attribute = enFilter)
|
||||
for e in result['response']:
|
||||
eid = e['Event']['id']
|
||||
einfo = e['Event']['info']
|
||||
eorgc = e['Event']['orgc']
|
||||
me = MaltegoEntity('maltego.MISPEvent',eid);
|
||||
me.addAdditionalFields('EventLink', 'EventLink', False, BASE_URL + '/events/view/' + eid )
|
||||
me.addAdditionalFields('Org', 'Org', False, eorgc)
|
||||
me.addAdditionalFields('notes#', 'notes', False, eorgc + ": " + einfo)
|
||||
mt.addEntityToMessage(me);
|
||||
return
|
||||
|
Loading…
Reference in New Issue