зеркало из https://github.com/mozilla/MozDef.git
185 строки
10 KiB
Python
185 строки
10 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
# Copyright (c) 2018 Mozilla Corporation
|
|
|
|
import json
|
|
from datetime import datetime
|
|
from platform import node
|
|
from mozdef_util.utilities.toUTC import toUTC
|
|
|
|
|
|
class message(object):
|
|
def __init__(self):
|
|
'''
|
|
takes an incoming suricata event
|
|
and parses the message to extract
|
|
data points, and sets the type
|
|
field
|
|
'''
|
|
|
|
self.registration = ['suricata']
|
|
self.priority = 5
|
|
try:
|
|
self.mozdefhostname = '{0}'.format(node())
|
|
except:
|
|
self.mozdefhostname = 'failed to fetch mozdefhostname'
|
|
pass
|
|
|
|
def onMessage(self, message, metadata):
|
|
|
|
# make sure I really wanted to see this message
|
|
# bail out early if not
|
|
if 'customendpoint' not in message:
|
|
return message, metadata
|
|
if 'category' not in message:
|
|
return message, metadata
|
|
if message['category'] != 'suricata':
|
|
return message, metadata
|
|
|
|
# move Suricata specific fields under 'details' while preserving metadata
|
|
newmessage = dict()
|
|
|
|
# Set NSM as type for categorical filtering of events.
|
|
newmessage["type"] = "nsm"
|
|
|
|
try:
|
|
newmessage['details'] = json.loads(message['message'])
|
|
except:
|
|
newmessage['details'] = {}
|
|
newmessage['rawdetails'] = message
|
|
|
|
# move some fields that are expected at the event 'root' where they belong
|
|
if 'host_from' in message:
|
|
newmessage['hostname'] = message['host_from']
|
|
if 'tags' in message:
|
|
newmessage['tags'] = message['tags']
|
|
if 'category' in message:
|
|
newmessage['category'] = message['category']
|
|
newmessage['source'] = 'unknown'
|
|
if 'source' in message:
|
|
newmessage['source'] = message['source']
|
|
logtype = newmessage['source']
|
|
newmessage['event_type'] = 'unknown'
|
|
if 'event_type' in message:
|
|
newmessage['event_type'] = message['event_type']
|
|
eventtype = newmessage['event_type']
|
|
|
|
# add mandatory fields
|
|
if 'flow' in newmessage['details']:
|
|
if 'start' in newmessage['details']['flow']:
|
|
newmessage['utctimestamp'] = toUTC(newmessage['details']['flow']['start']).isoformat()
|
|
newmessage['timestamp'] = toUTC(newmessage['details']['flow']['start']).isoformat()
|
|
else:
|
|
# a malformed message somehow managed to crawl to us, let's put it somewhat together
|
|
newmessage['utctimestamp'] = toUTC(datetime.now()).isoformat()
|
|
newmessage['timestamp'] = toUTC(datetime.now()).isoformat()
|
|
|
|
newmessage['receivedtimestamp'] = toUTC(datetime.now()).isoformat()
|
|
newmessage['eventsource'] = 'nsm'
|
|
newmessage['severity'] = 'INFO'
|
|
newmessage['mozdefhostname'] = self.mozdefhostname
|
|
|
|
if 'details' in newmessage:
|
|
newmessage['details']['sourceipaddress'] = "0.0.0.0"
|
|
newmessage['details']['destinationipaddress'] = "0.0.0.0"
|
|
newmessage['details']['sourceport'] = 0
|
|
newmessage['details']['destinationport'] = 0
|
|
if 'alert' in newmessage['details']:
|
|
newmessage['details']['suricata_alert'] = newmessage['details']['alert']
|
|
del(newmessage['details']['alert'])
|
|
if 'src_ip' in newmessage['details']:
|
|
newmessage['details']['sourceipaddress'] = newmessage['details']['src_ip']
|
|
del(newmessage['details']['src_ip'])
|
|
if 'src_port' in newmessage['details']:
|
|
newmessage['details']['sourceport'] = newmessage['details']['src_port']
|
|
del(newmessage['details']['src_port'])
|
|
if 'dest_ip' in newmessage['details']:
|
|
newmessage['details']['destinationipaddress'] = newmessage['details']['dest_ip']
|
|
del(newmessage['details']['dest_ip'])
|
|
if 'dest_port' in newmessage['details']:
|
|
newmessage['details']['destinationport'] = newmessage['details']['dest_port']
|
|
del(newmessage['details']['dest_port'])
|
|
|
|
if 'file_name' in newmessage['details']:
|
|
del(newmessage['details']['file_name'])
|
|
if 'message' in newmessage['details']:
|
|
del(newmessage['details']['message'])
|
|
if 'source' in newmessage['details']:
|
|
del(newmessage['details']['source'])
|
|
|
|
if logtype == 'eve-log':
|
|
if eventtype == 'alert':
|
|
# Truncate packet, payload and payload_printable to reasonable sizes
|
|
if 'packet' in newmessage['details']:
|
|
newmessage['details']['packet'] = newmessage['details']['packet'][0:4095]
|
|
if 'payload' in newmessage['details']:
|
|
newmessage['details']['payload'] = newmessage['details']['payload'][0:4095]
|
|
if 'payload_printable' in newmessage['details']:
|
|
newmessage['details']['payload_printable'] = newmessage['details']['payload_printable'][0:4095]
|
|
# Match names to Bro
|
|
newmessage['details']['originipbytes'] = 0
|
|
newmessage['details']['responseipbytes'] = 0
|
|
newmessage['details']['orig_pkts'] = 0
|
|
newmessage['details']['resp_pkts'] = 0
|
|
if 'flow' in newmessage['details']:
|
|
if 'bytes_toserver' in newmessage['details']['flow']:
|
|
newmessage['details']['originipbytes'] = newmessage['details']['flow']['bytes_toserver']
|
|
del(newmessage['details']['flow']['bytes_toserver'])
|
|
if 'bytes_toclient' in newmessage['details']['flow']:
|
|
newmessage['details']['responseipbytes'] = newmessage['details']['flow']['bytes_toclient']
|
|
del(newmessage['details']['flow']['bytes_toclient'])
|
|
if 'pkts_toserver' in newmessage['details']['flow']:
|
|
newmessage['details']['orig_pkts'] = newmessage['details']['flow']['pkts_toserver']
|
|
del(newmessage['details']['flow']['pkts_toserver'])
|
|
if 'pkts_toclient' in newmessage['details']['flow']:
|
|
newmessage['details']['resp_pkts'] = newmessage['details']['flow']['pkts_toclient']
|
|
del(newmessage['details']['flow']['pkts_toclient'])
|
|
if 'http' in newmessage['details']:
|
|
if 'hostname' in newmessage['details']['http']:
|
|
newmessage['details']['host'] = newmessage['details']['http']['hostname']
|
|
del(newmessage['details']['http']['hostname'])
|
|
if 'http_method' in newmessage['details']['http']:
|
|
newmessage['details']['method'] = newmessage['details']['http']['http_method']
|
|
del(newmessage['details']['http']['http_method'])
|
|
if 'http_user_agent' in newmessage['details']['http']:
|
|
newmessage['details']['user_agent'] = newmessage['details']['http']['http_user_agent']
|
|
del(newmessage['details']['http']['http_user_agent'])
|
|
if 'status' in newmessage['details']['http']:
|
|
newmessage['details']['status_code'] = newmessage['details']['http']['status']
|
|
del(newmessage['details']['http']['status'])
|
|
if 'url' in newmessage['details']['http']:
|
|
newmessage['details']['uri'] = newmessage['details']['http']['url']
|
|
del(newmessage['details']['http']['url'])
|
|
if 'redirect' in newmessage['details']['http']:
|
|
newmessage['details']['redirect_dst'] = newmessage['details']['http']['redirect']
|
|
del(newmessage['details']['http']['redirect'])
|
|
if 'length' in newmessage['details']['http']:
|
|
newmessage['details']['request_body_len'] = newmessage['details']['http']['length']
|
|
del(newmessage['details']['http']['length'])
|
|
if 'http_response_body' in newmessage['details']['http']:
|
|
newmessage['details']['http_response_body'] = newmessage['details']['http']['http_response_body'][0:4095]
|
|
del(newmessage['details']['http']['http_response_body'])
|
|
if 'http_response_body_printable' in newmessage['details']['http']:
|
|
newmessage['details']['http_response_body_printable'] = newmessage['details']['http']['http_response_body_printable'][0:4095]
|
|
del(newmessage['details']['http']['http_response_body_printable'])
|
|
if 'app_proto' in newmessage['details']:
|
|
newmessage['details']['service'] = newmessage['details']['app_proto']
|
|
del(newmessage['details']['app_proto'])
|
|
# Make sure details.vars.flowbits exceptions are handled
|
|
if 'vars' in newmessage['details']:
|
|
if 'flowbits' in newmessage['details']['vars']:
|
|
if 'ET.http.javaclient' in newmessage['details']['vars']['flowbits']:
|
|
if 'ET.http.javaclient.vulnerable':
|
|
del(newmessage['details']['vars']['flowbits']['ET.http.javaclient'])
|
|
newmessage['details']['vars']['flowbits']['ET.http.javaclient.vulnerable'] = "True"
|
|
newmessage['summary'] = (
|
|
'{sourceipaddress}:'+
|
|
'{sourceport} -> '+
|
|
'{destinationipaddress}:'
|
|
'{destinationport}'
|
|
).format(**newmessage['details'])
|
|
return (newmessage, metadata)
|
|
|
|
return (newmessage, metadata)
|