misp-modules/misp_modules/modules/expansion/yeti.py

164 lines
5.7 KiB
Python
Raw Normal View History

2021-02-05 10:18:52 +01:00
import json
try:
import pyeti
except ImportError:
print("pyeti module not installed.")
2021-03-05 19:01:25 +01:00
from pymisp import MISPEvent, MISPObject
2021-02-05 10:18:52 +01:00
misperrors = {'error': 'Error'}
mispattributes = {'input': ['ip-src', 'ip-dst', 'hostname', 'domain'],
2021-03-05 16:53:49 +01:00
'format': 'misp_standard'
}
2021-02-05 10:18:52 +01:00
# possible module-types: 'expansion', 'hover' or both
moduleinfo = {'version': '1', 'author': 'Sebastien Larinier @sebdraven',
'description': 'Query on yeti',
'module-type': ['expansion', 'hover']}
2021-02-05 11:17:40 +01:00
moduleconfig = ['apikey', 'url']
2021-03-05 11:34:01 +01:00
class Yeti():
2021-02-05 11:17:40 +01:00
2021-03-05 19:01:25 +01:00
def __init__(self, url, key,attribute):
2021-03-19 10:52:48 +01:00
self.misp_mapping = {'Ip': 'ip-dst', 'Domain': 'domain', 'Hostname': 'hostname', 'Url': 'url'}
2021-03-05 11:40:11 +01:00
self.yeti_client = pyeti.YetiApi(url=url, api_key=key)
2021-03-05 19:01:25 +01:00
self.attribute = attribute
self.misp_event = MISPEvent()
2021-03-19 15:55:18 +01:00
self.misp_event.add_attribute(**attribute)
2021-02-05 11:17:40 +01:00
def search(self, value):
2021-03-05 11:34:01 +01:00
obs = self.yeti_client.observable_search(value=value)
2021-02-05 11:17:40 +01:00
if obs:
return obs[0]
2021-02-05 11:17:40 +01:00
def get_neighboors(self, obs_id):
2021-03-05 11:34:01 +01:00
neighboors = self.yeti_client.neighbors_observables(obs_id)
if neighboors and 'objs' in neighboors:
2021-03-05 15:19:30 +01:00
for n in neighboors['objs']:
yield n
def get_tags(self, value):
obs = self.search(value)
if obs:
for t in obs['tags']:
yield t
def get_entity(self, obs_id):
2021-03-05 11:34:01 +01:00
companies = self.yeti_client.observable_to_company(obs_id)
actors = self.yeti_client.observable_to_actor(obs_id)
campaigns = self.yeti_client.observable_to_campaign(obs_id)
exploit_kit = self.yeti_client.observable_to_exploitkit(obs_id)
exploit = self.yeti_client.observable_to_exploit(obs_id)
ind = self.yeti_client.observable_to_indicator(obs_id)
res = []
res.extend(companies)
res.extend(actors)
res.extend(campaigns)
res.extend(exploit)
res.extend(exploit_kit)
res.extend(ind)
for r in res:
yield r['name']
2021-02-05 11:37:34 +01:00
2021-03-05 19:01:25 +01:00
def parse_yeti_result(self):
obs = self.search(self.attribute['value'])
values = []
types = []
for obs_to_add in self.get_neighboors(obs['id']):
object_misp_domain_ip = self.__get_object_domain_ip(obs_to_add)
if object_misp_domain_ip:
self.misp_event.add_object(object_misp_domain_ip)
2021-04-19 11:49:24 +02:00
object_misp_url = self.__get_object_url(obs_to_add)
if object_misp_url:
self.misp_event.add_object(object_misp_url)
2021-03-19 15:37:49 +01:00
2021-03-05 19:01:25 +01:00
def get_result(self):
event = json.loads(self.misp_event.to_json())
results = {key: event[key] for key in ('Attribute', 'Object')}
print('results %s' % results)
2021-03-05 19:01:25 +01:00
return results
def __get_object_domain_ip(self, obj_to_add):
2021-04-19 11:00:55 +02:00
if (obj_to_add['type'] == 'Ip' and self.attribute['type'] in ['hostname','domain']) or\
2021-03-05 19:01:25 +01:00
(obj_to_add['type'] in ('Hostname', 'Domain') and self.attribute['type'] in ('ip-src', 'ip-dst')):
domain_ip_object = MISPObject('domain-ip')
2021-03-19 15:16:00 +01:00
domain_ip_object.add_attribute(self.__get_relation(obj_to_add),
obj_to_add['value'])
domain_ip_object.add_attribute(self.__get_relation(self.attribute, is_yeti_object=False),
self.attribute['value'])
2021-03-19 15:16:00 +01:00
domain_ip_object.add_reference(self.attribute['uuid'], 'related_to')
2021-03-05 19:01:25 +01:00
return domain_ip_object
def __get_object_url(self, obj_to_add):
2021-04-19 11:03:39 +02:00
if (obj_to_add['type'] == 'Url' and self.attribute['type'] in ['hostname', 'domain', 'ip-src', 'ip-dst']) or (
2021-04-19 11:00:55 +02:00
obj_to_add['type'] in ('Hostname', 'Domain', 'Ip') and self.attribute['type'] == 'url'
):
url_object = MISPObject('Url')
2021-04-19 11:24:01 +02:00
obj_relation = self.__get_relation(obj_to_add)
if obj_relation:
2021-04-19 11:49:24 +02:00
url_object.add_attribute(obj_relation, obj_to_add['value'])
2021-04-19 11:24:01 +02:00
obj_relation = self.__get_relation(self.attribute)
if obj_relation:
url_object.add_attribute(self.__get_relation(self.attribute),
self.attribute['value'])
2021-04-19 11:24:01 +02:00
url_object.add_reference(self.attribute['uuid'], 'related_to')
2021-04-19 11:05:16 +02:00
print(url_object)
return url_object
def __get_relation(self, obj, is_yeti_object=True):
if is_yeti_object:
type_attribute = self.misp_mapping[obj['type']]
else:
type_attribute = obj['type']
if type_attribute == 'ip-src' or type_attribute == 'ip-dst':
2021-03-19 15:16:00 +01:00
return 'ip'
elif 'domain' == type_attribute:
2021-03-19 15:16:00 +01:00
return 'domain'
elif 'hostname' == type_attribute:
2021-03-19 15:16:00 +01:00
return 'domain'
elif type_attribute == 'url':
2021-04-19 11:09:38 +02:00
return type_attribute
2021-03-19 10:52:48 +01:00
2021-03-19 11:40:23 +01:00
2021-02-05 11:17:40 +01:00
def handler(q=False):
if q is False:
return False
2021-03-05 11:34:01 +01:00
apikey = None
yeti_url = None
2021-03-05 11:34:01 +01:00
yeti_client = None
request = json.loads(q)
2021-03-05 19:01:25 +01:00
attribute = request['attribute']
if attribute['type'] not in mispattributes['input']:
return {'error': 'Unsupported attributes type'}
2021-03-19 11:01:02 +01:00
if 'config' in request and 'url' in request['config']:
yeti_url = request['config']['url']
if 'config' in request and 'apikey' in request['config']:
apikey = request['config']['apikey']
2021-03-05 11:22:53 +01:00
if apikey and yeti_url:
2021-03-05 19:01:25 +01:00
yeti_client = Yeti(yeti_url, apikey, attribute)
2021-03-05 11:22:53 +01:00
if yeti_client:
2021-03-19 10:52:48 +01:00
yeti_client.parse_yeti_result()
2021-03-19 15:55:18 +01:00
return {'results': yeti_client.get_result()}
2021-03-05 11:22:53 +01:00
else:
misperrors['error'] = 'Yeti Config Error'
return misperrors
2021-02-05 11:47:27 +01:00
def version():
moduleinfo['config'] = moduleconfig
return moduleinfo
def introspection():
return mispattributes