2016-08-12 13:48:45 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
2019-07-17 16:46:47 +02:00
|
|
|
#
|
2016-08-12 13:48:45 +02:00
|
|
|
# Copy Emerging Threats Block IPs list to several MISP events
|
2016-08-18 11:27:02 +02:00
|
|
|
# Because of the large size of the list the first run will take a minute
|
2016-08-12 13:48:45 +02:00
|
|
|
# Running it again will update the MISP events if changes are detected
|
|
|
|
#
|
|
|
|
# This script requires PyMISP 2.4.50 or later
|
|
|
|
|
|
|
|
import sys, json, time, requests
|
|
|
|
from pymisp import PyMISP
|
2018-10-14 19:26:03 +02:00
|
|
|
from keys import misp_url, misp_key, misp_verifycert
|
2016-08-12 13:48:45 +02:00
|
|
|
|
|
|
|
et_url = 'https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt'
|
|
|
|
et_str = 'Emerging Threats '
|
|
|
|
|
|
|
|
def init_misp():
|
|
|
|
global mymisp
|
2018-10-14 19:26:03 +02:00
|
|
|
mymisp = PyMISP(misp_url, misp_key, misp_verifycert)
|
2016-08-12 13:48:45 +02:00
|
|
|
|
|
|
|
def load_misp_event(eid):
|
|
|
|
global et_attr
|
|
|
|
global et_drev
|
|
|
|
global et_event
|
|
|
|
et_attr = {}
|
|
|
|
et_drev = {}
|
2019-07-17 16:46:47 +02:00
|
|
|
|
2016-08-12 13:48:45 +02:00
|
|
|
et_event = mymisp.get(eid)
|
|
|
|
echeck(et_event)
|
|
|
|
for a in et_event['Event']['Attribute']:
|
|
|
|
if a['category'] == 'Network activity':
|
|
|
|
et_attr[a['value']] = a['id']
|
|
|
|
continue
|
|
|
|
if a['category'] == 'Internal reference':
|
|
|
|
et_drev = a;
|
|
|
|
|
|
|
|
def init_et():
|
|
|
|
global et_data
|
|
|
|
global et_rev
|
|
|
|
requests.packages.urllib3.disable_warnings()
|
|
|
|
s = requests.Session()
|
|
|
|
r = s.get(et_url)
|
|
|
|
if r.status_code != 200:
|
|
|
|
raise Exception('Error getting ET data: {}'.format(r.text))
|
|
|
|
name = ''
|
|
|
|
et_data = {}
|
|
|
|
et_rev = 0
|
|
|
|
for line in r.text.splitlines():
|
|
|
|
if line.startswith('# Rev '):
|
|
|
|
et_rev = int(line[6:])
|
|
|
|
continue
|
|
|
|
if line.startswith('#'):
|
|
|
|
name = line[1:].strip()
|
|
|
|
if et_rev and not et_data.get(name):
|
|
|
|
et_data[name] = {}
|
|
|
|
continue
|
|
|
|
l = line.rstrip()
|
|
|
|
if l:
|
|
|
|
et_data[name][l] = name
|
|
|
|
|
|
|
|
def update_et_event(name):
|
|
|
|
if et_drev and et_rev and int(et_drev['value']) < et_rev:
|
|
|
|
# Copy MISP attributes to new dict
|
|
|
|
et_ips = dict.fromkeys(et_attr.keys())
|
|
|
|
|
|
|
|
# Weed out attributes still in ET data
|
|
|
|
for k,v in et_data[name].items():
|
|
|
|
et_attr.pop(k, None)
|
2019-07-17 16:46:47 +02:00
|
|
|
|
2016-08-12 13:48:45 +02:00
|
|
|
# Delete the leftover attributes from MISP
|
|
|
|
for k,v in et_attr.items():
|
|
|
|
r = mymisp.delete_attribute(v)
|
|
|
|
if r.get('errors'):
|
2020-01-03 15:42:41 +01:00
|
|
|
print("Error deleting attribute {} ({}): {}\n".format(v,k,r['errors']))
|
2016-08-12 13:48:45 +02:00
|
|
|
|
|
|
|
# Weed out ips already in the MISP event
|
|
|
|
for k,v in et_ips.items():
|
|
|
|
et_data[name].pop(k, None)
|
|
|
|
|
|
|
|
# Add new attributes to MISP event
|
2016-08-18 11:27:02 +02:00
|
|
|
ipdst = []
|
|
|
|
for i,k in enumerate(et_data[name].items(), 1-len(et_data[name])):
|
|
|
|
ipdst.append(k[0])
|
|
|
|
if i % 100 == 0:
|
|
|
|
r = mymisp.add_ipdst(et_event, ipdst)
|
|
|
|
echeck(r, et_event['Event']['id'])
|
|
|
|
ipdst = []
|
2016-08-12 13:48:45 +02:00
|
|
|
|
|
|
|
# Update revision number
|
|
|
|
et_drev['value'] = et_rev
|
|
|
|
et_drev.pop('timestamp', None)
|
|
|
|
attr = []
|
|
|
|
attr.append(et_drev)
|
|
|
|
|
2019-07-17 16:46:47 +02:00
|
|
|
# Publish updated MISP event
|
2016-08-12 13:48:45 +02:00
|
|
|
et_event['Event']['Attribute'] = attr
|
|
|
|
et_event['Event']['published'] = False
|
|
|
|
et_event['Event']['date'] = time.strftime('%Y-%m-%d')
|
|
|
|
r = mymisp.publish(et_event)
|
|
|
|
echeck(r, et_event['Event']['id'])
|
|
|
|
|
|
|
|
def echeck(r, eid=None):
|
|
|
|
if r.get('errors'):
|
|
|
|
if eid:
|
2020-01-03 15:42:41 +01:00
|
|
|
print("Processing event {} failed: {}".format(eid, r['errors']))
|
2016-08-12 13:48:45 +02:00
|
|
|
else:
|
2020-01-03 15:42:41 +01:00
|
|
|
print(r['errors'])
|
2016-08-12 13:48:45 +02:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
init_misp()
|
|
|
|
init_et()
|
|
|
|
|
|
|
|
for et_type in set(et_data.keys()):
|
|
|
|
info = et_str + et_type
|
|
|
|
r = mymisp.search_index(eventinfo=info)
|
|
|
|
if r['response']:
|
|
|
|
eid=r['response'][0]['id']
|
|
|
|
else: # event not found, create it
|
|
|
|
new_event = mymisp.new_event(info=info, distribution=3, threat_level_id=4, analysis=1)
|
|
|
|
echeck(new_event)
|
|
|
|
eid=new_event['Event']['id']
|
|
|
|
r = mymisp.add_internal_text(new_event, 1, comment='Emerging Threats revision number')
|
|
|
|
echeck(r, eid)
|
|
|
|
load_misp_event(eid)
|
|
|
|
update_et_event(et_type)
|