mirror of https://github.com/MISP/PyMISP
fix: Properly create fail2ban object
parent
22c874e479
commit
9e44ec6616
|
@ -5,6 +5,9 @@ from pymisp import PyMISP, MISPEvent
|
||||||
from pymisp.tools import Fail2BanObject
|
from pymisp.tools import Fail2BanObject
|
||||||
import argparse
|
import argparse
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
from datetime import date, datetime
|
||||||
|
from dateutil.parser import parse
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from keys import misp_url, misp_key, misp_verifycert
|
from keys import misp_url, misp_key, misp_verifycert
|
||||||
|
@ -14,29 +17,52 @@ except Exception:
|
||||||
misp_key = True
|
misp_key = True
|
||||||
|
|
||||||
|
|
||||||
|
def create_new_event():
|
||||||
|
me = MISPEvent()
|
||||||
|
me.info = "Fail2Ban blocking"
|
||||||
|
me.add_tag(args.tag)
|
||||||
|
start = datetime.now()
|
||||||
|
me.add_attribute('datetime', start.isoformat(), comment='Start Time')
|
||||||
|
return me
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(description='Add Fail2ban object.')
|
parser = argparse.ArgumentParser(description='Add Fail2ban object.')
|
||||||
parser.add_argument("-b", "--banned_ip", required=True, help="Banned IP address.")
|
parser.add_argument("-b", "--banned_ip", required=True, help="Banned IP address.")
|
||||||
parser.add_argument("-a", "--attack_type", required=True, help="Type of attack.")
|
parser.add_argument("-a", "--attack_type", required=True, help="Type of attack.")
|
||||||
|
parser.add_argument("-t", "--tag", required=True, help="Tag to search on MISP.")
|
||||||
parser.add_argument("-p", "--processing_timestamp", help="Processing timestamp.")
|
parser.add_argument("-p", "--processing_timestamp", help="Processing timestamp.")
|
||||||
parser.add_argument("-f", "--failures", help="Amount of failures that lead to the ban.")
|
parser.add_argument("-f", "--failures", help="Amount of failures that lead to the ban.")
|
||||||
parser.add_argument("-s", "--sensor", help="Sensor identifier.")
|
parser.add_argument("-s", "--sensor", help="Sensor identifier.")
|
||||||
parser.add_argument("-v", "--victim", help="Victim identifier.")
|
parser.add_argument("-v", "--victim", help="Victim identifier.")
|
||||||
parser.add_argument("-l", "--logline", help="Logline (base64 encoded).")
|
parser.add_argument("-l", "--logline", help="Logline (base64 encoded).")
|
||||||
parser.add_argument("-ap", "--aggregation_period", required=True, help="Max time of the event (1d, 1h, ...).")
|
parser.add_argument("-n", "--force_new", action='store_true', default=False, help="Force new MISP event.")
|
||||||
parser.add_argument("-t", "--tag", required=True, help="Tag to search on MISP.")
|
parser.add_argument("-d", "--disable_new", action='store_true', default=False, help="Do not create a new Event.")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
pymisp = PyMISP(misp_url, misp_key, misp_verifycert, debug=True)
|
pymisp = PyMISP(misp_url, misp_key, misp_verifycert, debug=True)
|
||||||
|
event_id = -1
|
||||||
response = pymisp.search(tags=args.tag, last=args.aggregation_period, published=False)
|
me = None
|
||||||
me = MISPEvent()
|
if args.force_new:
|
||||||
if 'response' in response and response['response']:
|
me = create_new_event()
|
||||||
me.load(response['response'][0])
|
|
||||||
else:
|
else:
|
||||||
me.info = "Fail2Ban blocking"
|
response = pymisp.search_index(tag=args.tag, timestamp='1h')
|
||||||
me.add_tag(args.tag)
|
if response['response']:
|
||||||
parameters = {'banned-ip': args.banned_ip, 'attack-type': args.attack_type, 'processing-timestamp': args.processing_timestamp}
|
if args.disable_new:
|
||||||
|
event_id = response['response'][0]['id']
|
||||||
|
else:
|
||||||
|
last_event_date = parse(response['response'][0]['date']).date()
|
||||||
|
nb_attr = response['response'][0]['attribute_count']
|
||||||
|
if last_event_date < date.today() or int(nb_attr) > 1000:
|
||||||
|
me = create_new_event()
|
||||||
|
else:
|
||||||
|
event_id = response['response'][0]['id']
|
||||||
|
else:
|
||||||
|
me = create_new_event()
|
||||||
|
|
||||||
|
parameters = {'banned-ip': args.banned_ip, 'attack-type': args.attack_type}
|
||||||
|
if args.processing_timestamp:
|
||||||
|
parameters['processing-timestamp'] = args.processing_timestamp
|
||||||
if args.failures:
|
if args.failures:
|
||||||
parameters['failures'] = args.failures
|
parameters['failures'] = args.failures
|
||||||
if args.sensor:
|
if args.sensor:
|
||||||
|
@ -46,5 +72,9 @@ if __name__ == '__main__':
|
||||||
if args.logline:
|
if args.logline:
|
||||||
parameters['logline'] = b64decode(args.logline).decode()
|
parameters['logline'] = b64decode(args.logline).decode()
|
||||||
f2b = Fail2BanObject(parameters=parameters, standalone=False)
|
f2b = Fail2BanObject(parameters=parameters, standalone=False)
|
||||||
|
if me:
|
||||||
me.add_object(f2b)
|
me.add_object(f2b)
|
||||||
pymisp.add_event(me)
|
pymisp.add_event(me)
|
||||||
|
elif event_id:
|
||||||
|
template_id = pymisp.get_object_template_id(f2b.template_uuid)
|
||||||
|
a = pymisp.add_object(event_id, template_id, f2b)
|
||||||
|
|
|
@ -953,7 +953,8 @@ class PyMISP(object):
|
||||||
|
|
||||||
def search_index(self, published=None, eventid=None, tag=None, datefrom=None,
|
def search_index(self, published=None, eventid=None, tag=None, datefrom=None,
|
||||||
dateuntil=None, eventinfo=None, threatlevel=None, distribution=None,
|
dateuntil=None, eventinfo=None, threatlevel=None, distribution=None,
|
||||||
analysis=None, attribute=None, org=None, async_callback=None, normalize=False):
|
analysis=None, attribute=None, org=None, async_callback=None, normalize=False,
|
||||||
|
timestamp=None):
|
||||||
"""Search only at the index level. Use ! infront of value as NOT, default OR
|
"""Search only at the index level. Use ! infront of value as NOT, default OR
|
||||||
If using async, give a callback that takes 2 args, session and response:
|
If using async, give a callback that takes 2 args, session and response:
|
||||||
basic usage is
|
basic usage is
|
||||||
|
@ -971,11 +972,12 @@ class PyMISP(object):
|
||||||
:param org: Organisation(s) | str or list
|
:param org: Organisation(s) | str or list
|
||||||
:param async_callback: Function to call when the request returns (if running async)
|
:param async_callback: Function to call when the request returns (if running async)
|
||||||
:param normalize: Normalize output | True or False
|
:param normalize: Normalize output | True or False
|
||||||
|
:param timestamp: Interval since last update (in second, or 1d, 1h, ...)
|
||||||
"""
|
"""
|
||||||
allowed = {'published': published, 'eventid': eventid, 'tag': tag, 'Dateuntil': dateuntil,
|
allowed = {'published': published, 'eventid': eventid, 'tag': tag, 'Dateuntil': dateuntil,
|
||||||
'Datefrom': datefrom, 'eventinfo': eventinfo, 'threatlevel': threatlevel,
|
'Datefrom': datefrom, 'eventinfo': eventinfo, 'threatlevel': threatlevel,
|
||||||
'distribution': distribution, 'analysis': analysis, 'attribute': attribute,
|
'distribution': distribution, 'analysis': analysis, 'attribute': attribute,
|
||||||
'org': org}
|
'org': org, 'timestamp': timestamp}
|
||||||
rule_levels = {'distribution': ["0", "1", "2", "3", "!0", "!1", "!2", "!3"],
|
rule_levels = {'distribution': ["0", "1", "2", "3", "!0", "!1", "!2", "!3"],
|
||||||
'threatlevel': ["1", "2", "3", "4", "!1", "!2", "!3", "!4"],
|
'threatlevel': ["1", "2", "3", "4", "!1", "!2", "!3", "!4"],
|
||||||
'analysis': ["0", "1", "2", "!0", "!1", "!2"]}
|
'analysis': ["0", "1", "2", "!0", "!1", "!2"]}
|
||||||
|
@ -1370,11 +1372,7 @@ class PyMISP(object):
|
||||||
raise Exception('Invalid parameter, org_id must be a number')
|
raise Exception('Invalid parameter, org_id must be a number')
|
||||||
else:
|
else:
|
||||||
org_id = ""
|
org_id = ""
|
||||||
uri = 'sightings/listSightings/{}/{}/{}'.format(
|
uri = 'sightings/listSightings/{}/{}/{}'.format(element_id, scope, org_id)
|
||||||
element_id,
|
|
||||||
scope,
|
|
||||||
org_id
|
|
||||||
)
|
|
||||||
url = urljoin(self.root_url, uri)
|
url = urljoin(self.root_url, uri)
|
||||||
response = self.__prepare_request('POST', url)
|
response = self.__prepare_request('POST', url)
|
||||||
return self._check_response(response)
|
return self._check_response(response)
|
||||||
|
|
|
@ -452,7 +452,7 @@ class MISPEvent(AbstractMISP):
|
||||||
def from_dict(self, **kwargs):
|
def from_dict(self, **kwargs):
|
||||||
# Required value
|
# Required value
|
||||||
self.info = kwargs.pop('info', None)
|
self.info = kwargs.pop('info', None)
|
||||||
if not self.info:
|
if self.info is None:
|
||||||
raise NewAttributeError('The info field of the new event is required.')
|
raise NewAttributeError('The info field of the new event is required.')
|
||||||
|
|
||||||
# Default values for a valid event to send to a MISP instance
|
# Default values for a valid event to send to a MISP instance
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -31,7 +31,8 @@ setup(
|
||||||
extras_require={'fileobjects': ['lief>=0.8', 'python-magic'],
|
extras_require={'fileobjects': ['lief>=0.8', 'python-magic'],
|
||||||
'neo': ['py2neo'],
|
'neo': ['py2neo'],
|
||||||
'openioc': ['beautifulsoup4'],
|
'openioc': ['beautifulsoup4'],
|
||||||
'virustotal': ['validators']},
|
'virustotal': ['validators'],
|
||||||
|
'warninglists': ['pymispwarninglists']},
|
||||||
tests_require=[
|
tests_require=[
|
||||||
'jsonschema',
|
'jsonschema',
|
||||||
'python-dateutil',
|
'python-dateutil',
|
||||||
|
|
Loading…
Reference in New Issue