mirror of
https://github.com/ail-project/ail-framework.git
synced 2024-11-23 06:37:15 +00:00
356 lines
10 KiB
Python
Executable file
356 lines
10 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# -*-coding:UTF-8 -*
|
|
|
|
import os
|
|
import sys
|
|
import uuid
|
|
|
|
sys.path.append(os.environ['AIL_BIN'])
|
|
##################################
|
|
# Import Project packages
|
|
##################################
|
|
from lib.ConfigLoader import ConfigLoader
|
|
from lib.objects.Items import Item
|
|
from lib.ail_core import get_ail_uuid
|
|
from lib.Investigations import Investigation
|
|
from lib.objects import ail_objects
|
|
|
|
## LOAD CONFIG ##
|
|
config_loader = ConfigLoader()
|
|
r_cache = config_loader.get_redis_conn("Redis_Cache")
|
|
r_db = config_loader.get_db_conn("Kvrocks_DB")
|
|
|
|
r_serv_db = config_loader.get_redis_conn("ARDB_DB") ######################################
|
|
r_serv_metadata = config_loader.get_redis_conn("ARDB_Metadata") ######################################
|
|
config_loader = None
|
|
## -- ##
|
|
|
|
sys.path.append('../../configs/keys')
|
|
##################################
|
|
# Import Keys
|
|
##################################
|
|
from thehive4py.api import TheHiveApi
|
|
from thehive4py.models import Alert, AlertArtifact, Case, CaseObservable
|
|
import thehive4py.exceptions
|
|
|
|
from pymisp import MISPEvent, MISPObject, PyMISP
|
|
|
|
##################################
|
|
# THE HIVE
|
|
##################################
|
|
|
|
HIVE_CLIENT = None
|
|
try:
|
|
from theHiveKEYS import the_hive_url, the_hive_key, the_hive_verifycert
|
|
|
|
HIVE_URL = the_hive_url
|
|
HIVE_KEY = the_hive_key
|
|
HIVE_VERIFY_CERT = the_hive_verifycert
|
|
except:
|
|
HIVE_URL = None
|
|
HIVE_KEY = None
|
|
HIVE_VERIFY_CERT = None
|
|
|
|
|
|
def get_hive_client():
|
|
global HIVE_CLIENT
|
|
try:
|
|
HIVE_CLIENT = TheHiveApi(HIVE_URL, HIVE_KEY, cert=HIVE_VERIFY_CERT)
|
|
except:
|
|
HIVE_CLIENT = None
|
|
return HIVE_CLIENT
|
|
|
|
|
|
def is_hive_connected():
|
|
try:
|
|
# print(hive_client.health())
|
|
HIVE_CLIENT.get_alert(0)
|
|
return True
|
|
except thehive4py.exceptions.AlertException:
|
|
return False
|
|
|
|
|
|
HIVE_CLIENT = get_hive_client()
|
|
|
|
def sanitize_threat_level_hive(threat_level):
|
|
try:
|
|
int(threat_level)
|
|
if 1 <= threat_level <= 3:
|
|
return threat_level
|
|
else:
|
|
return 2
|
|
except:
|
|
return 2
|
|
|
|
def sanitize_tlp_hive(tlp):
|
|
try:
|
|
int(tlp)
|
|
if 0 <= tlp <= 3:
|
|
return tlp
|
|
else:
|
|
return 2
|
|
except:
|
|
return 2
|
|
|
|
def create_thehive_alert(item_id, tag_trigger):
|
|
item = Item(item_id)
|
|
meta = item.get_meta()
|
|
# TheHive expects a file
|
|
content = item.get_raw_content(decompress=True)
|
|
|
|
# remove .gz from submitted path to TheHive because we've decompressed it
|
|
if item_id.endswith(".gz"):
|
|
item_id = item_id[:-3]
|
|
# add .txt it's easier to open when downloaded from TheHive
|
|
item_id = f'{item_id}.txt'
|
|
|
|
artifacts = [
|
|
AlertArtifact(dataType='other', message='uuid-ail', data=(get_ail_uuid())),
|
|
AlertArtifact(dataType='file', data=(content, item_id), tags=meta['tags'])
|
|
]
|
|
|
|
# Prepare the sample Alert
|
|
sourceRef = str(uuid.uuid4())[0:6]
|
|
alert = Alert(title='AIL Leak',
|
|
tlp=3,
|
|
tags=meta['tags'],
|
|
description='AIL Leak, triggered by {}'.format(tag_trigger),
|
|
type='ail',
|
|
source=meta['source'], # Use item ID ?
|
|
sourceRef=sourceRef,
|
|
artifacts=artifacts)
|
|
|
|
# Create the Alert
|
|
alert_id = None
|
|
try:
|
|
response = HIVE_CLIENT.create_alert(alert)
|
|
if response.status_code == 201:
|
|
# print(json.dumps(response.json(), indent=4, sort_keys=True))
|
|
print('Alert Created')
|
|
print(response.json())
|
|
alert_id = response.json()['id']
|
|
else:
|
|
print(f'ko: {response.status_code}/{response.text}')
|
|
return 0
|
|
except:
|
|
print('hive connection error')
|
|
print(alert_id)
|
|
|
|
|
|
# TODO SAVE CASE URL ????????????????????????
|
|
def create_thehive_case(item_id, title=None, tlp=2, threat_level=2, description=None):
|
|
item = Item(item_id)
|
|
ail_uuid = get_ail_uuid()
|
|
|
|
if not title:
|
|
title = f'AIL Case {item.id}'
|
|
if not description:
|
|
description = f'AIL {ail_uuid} Case'
|
|
date = item.get_date()
|
|
date = f'{date[0:4]}-{date[4:6]}-{date[6:8]}'
|
|
tags = item.get_tags(r_list=True)
|
|
|
|
case = Case(title=title,
|
|
tlp=tlp,
|
|
severity=threat_level,
|
|
flag=False,
|
|
tags=tags,
|
|
description=description)
|
|
|
|
# Create Case
|
|
response = get_hive_client().create_case(case)
|
|
if response.status_code == 201:
|
|
case_id = response.json()['id']
|
|
|
|
observables = [
|
|
CaseObservable(dataType="other", data=[ail_uuid], message="uuid-ail"),
|
|
CaseObservable(dataType="file", data=item.get_filename(), tags=tags),
|
|
CaseObservable(dataType="other", data=[item.get_source()], message="source"),
|
|
CaseObservable(dataType="other", data=[date], message="last-seen")
|
|
]
|
|
|
|
for observable in observables:
|
|
resp = HIVE_CLIENT.create_case_observable(case_id, observable)
|
|
if resp.status_code != 201:
|
|
print(f'error observable creation: {resp.status_code}/{resp.text}')
|
|
# print(case_id)
|
|
# return HIVE_URL /thehive/cases/~37040/details
|
|
return case_id
|
|
|
|
# r_serv_metadata.set('hive_cases:'+path, id)
|
|
else:
|
|
print(f'ko: {response.status_code}/{response.text}')
|
|
return None
|
|
|
|
|
|
def get_case_url(case_id):
|
|
return f'{HIVE_URL}/cases/{case_id}/details'
|
|
|
|
|
|
# TODO
|
|
def get_item_hive_cases(item_id):
|
|
hive_case = r_serv_metadata.get('hive_cases:{}'.format(item_id))
|
|
if hive_case:
|
|
hive_case = the_hive_url + '/index.html#/case/{}/details'.format(hive_case)
|
|
return hive_case
|
|
|
|
|
|
##################################
|
|
# MISP
|
|
##################################
|
|
|
|
try:
|
|
from mispKEYS import misp_url, misp_key, misp_verifycert
|
|
|
|
MISP_URL = misp_url
|
|
MISP_KEY = misp_key
|
|
MISP_VERIFYCERT = misp_verifycert
|
|
if MISP_URL.endswith('/'):
|
|
MISP_URL = MISP_URL[:-1]
|
|
except:
|
|
MISP_URL = None
|
|
MISP_KEY = None
|
|
MISP_VERIFYCERT = None
|
|
|
|
|
|
def get_misp_client():
|
|
return PyMISP(misp_url, misp_key, misp_verifycert)
|
|
|
|
|
|
# # TODO: return error
|
|
def ping_misp():
|
|
try:
|
|
PyMISP(misp_url, misp_key, misp_verifycert)
|
|
return True
|
|
except Exception as e:
|
|
print(e)
|
|
return False
|
|
|
|
|
|
def sanitize_misp_event_distribution(distribution):
|
|
try:
|
|
int(distribution)
|
|
if 0 <= distribution <= 3:
|
|
return distribution
|
|
else:
|
|
return 0
|
|
except:
|
|
return 0
|
|
|
|
|
|
def sanitize_misp_event_threat_level(threat_level):
|
|
try:
|
|
int(threat_level)
|
|
if 1 <= threat_level <= 4:
|
|
return threat_level
|
|
else:
|
|
return 4
|
|
except:
|
|
return 4
|
|
|
|
|
|
def sanitize_misp_event_analysis(analysis):
|
|
try:
|
|
int(analysis)
|
|
if 0 <= analysis <= 2:
|
|
return analysis
|
|
else:
|
|
return 0
|
|
except:
|
|
return 0
|
|
|
|
def create_misp_event(objs, event_uuid=None, date=None, distribution=0, threat_level_id=4, publish=False, analysis=0,
|
|
info=None, tags=None, export=False):
|
|
if tags is None:
|
|
tags = []
|
|
event = MISPEvent()
|
|
if not event_uuid:
|
|
event_uuid = str(uuid.uuid4())
|
|
event.uuid = event_uuid
|
|
if date:
|
|
event.date = date
|
|
if not info:
|
|
info = 'AIL framework export'
|
|
event.info = info
|
|
if publish:
|
|
event.publish()
|
|
for tag in tags:
|
|
event.add_tag(tag)
|
|
event.distribution = sanitize_misp_event_distribution(distribution)
|
|
event.threat_level_id = sanitize_misp_event_threat_level(threat_level_id)
|
|
event.analysis = sanitize_misp_event_analysis(analysis)
|
|
|
|
misp_objects = ail_objects.get_misp_objects(objs)
|
|
for obj in misp_objects:
|
|
event.add_object(obj)
|
|
|
|
# print(event.to_json())
|
|
|
|
if export:
|
|
misp = get_misp_client()
|
|
misp_event = misp.add_event(event)
|
|
# TODO: handle error
|
|
|
|
misp_event['url'] = f'{MISP_URL}/events/view/{misp_event["Event"]["uuid"]}'
|
|
return misp_event
|
|
else:
|
|
return {'uuid': event['uuid'], 'event': event.to_json()}
|
|
|
|
def create_investigation_misp_event(investigation_uuid):
|
|
investigation = Investigation(investigation_uuid)
|
|
objs = ail_objects.get_objects(investigation.get_objects())
|
|
|
|
event = create_misp_event(objs,
|
|
# event_uuid=investigation.get_uuid(separator=True), # TODO EDIT EXISTING EVENT ????
|
|
date=investigation.get_date(),
|
|
distribution=0,
|
|
threat_level_id=investigation.get_threat_level(),
|
|
analysis=investigation.get_analysis(),
|
|
info=investigation.get_info(),
|
|
tags=investigation.get_tags(),
|
|
export=True)
|
|
url = event['url']
|
|
if url:
|
|
investigation.add_misp_events(url)
|
|
return url
|
|
|
|
def get_user_misp_objects_to_export(user_id):
|
|
objs = []
|
|
objects = r_db.hgetall(f'user:obj:misp:export:{user_id}')
|
|
for obj in objects:
|
|
obj_type, obj_subtype, obj_id = obj.split(':', 2)
|
|
lvl = objects[obj]
|
|
try:
|
|
lvl = int(lvl)
|
|
except:
|
|
lvl = 0
|
|
objs.append({'type': obj_type, 'subtype': obj_subtype, 'id': obj_id, 'lvl': lvl})
|
|
return objs
|
|
|
|
def add_user_misp_object_to_export(user_id, obj_type, obj_subtype, obj_id, lvl=0):
|
|
if not obj_subtype:
|
|
obj_subtype = ''
|
|
r_db.hset(f'user:obj:misp:export:{user_id}', f'{obj_type}:{obj_subtype}:{obj_id}', lvl)
|
|
|
|
def delete_user_misp_object_to_export(user_id, obj_type, obj_subtype, obj_id):
|
|
r_db.hdel(f'user:obj:misp:export:{user_id}', f'{obj_type}:{obj_subtype}:{obj_id}')
|
|
|
|
def delete_user_misp_objects_to_export(user_id):
|
|
r_db.delete(f'user:obj:misp:export:{user_id}')
|
|
|
|
|
|
###########################################################
|
|
# # set default
|
|
# if r_serv_db.get('hive:auto-alerts') is None:
|
|
# r_serv_db.set('hive:auto-alerts', 0)
|
|
#
|
|
# if r_serv_db.get('misp:auto-events') is None:
|
|
# r_serv_db.set('misp:auto-events', 0)
|
|
|
|
# if __name__ == '__main__':
|
|
# from lib.objects.Cves import Cve
|
|
# create_misp_event([Item('crawled/2020/09/14/circl.lu0f4976a4-dda4-4189-ba11-6618c4a8c951'),
|
|
# Cve('CVE-2020-16856'), Cve('CVE-2014-6585'), Cve('CVE-2015-0383'),
|
|
# Cve('CVE-2015-0410')])
|
|
|
|
# create_investigation_misp_event('c6bbf8fa9ead4cc698eaeb07835cca5d)
|