Skip to content

EQL Query Generation Modules #346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Oct 30, 2019
2 changes: 1 addition & 1 deletion misp_modules/modules/expansion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
sys.path.append('{}/lib'.format('/'.join((os.path.realpath(__file__)).split('/')[:-3])))

__all__ = ['cuckoo_submit', 'vmray_submit', 'bgpranking', 'circl_passivedns', 'circl_passivessl',
'countrycode', 'cve', 'cve_advanced', 'dns', 'btc_steroids', 'domaintools', 'eupi',
'countrycode', 'cve', 'cve_advanced', 'dns', 'btc_steroids', 'domaintools', 'eupi', 'eql',
'farsight_passivedns', 'ipasn', 'passivetotal', 'sourcecache', 'virustotal',
'whois', 'shodan', 'reversedns', 'geoip_country', 'wiki', 'iprep',
'threatminer', 'otx', 'threatcrowd', 'vulndb', 'crowdstrike_falcon',
Expand Down
84 changes: 84 additions & 0 deletions misp_modules/modules/expansion/eql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""
Export module for converting MISP events into Endgame EQL queries
"""
import json
import logging

misperrors = {"error": "Error"}

moduleinfo = {
"version": "0.1",
"author": "92 COS DOM",
"description": "Generates EQL queries from events",
"module-type": ["expansion"]
}

# Map of MISP fields => Endgame fields
fieldmap = {
"ip-src": "source_address",
"ip-dst": "destination_address",
"filename": "file_name"
}

# Describe what events have what fields
event_types = {
"source_address": "network",
"destination_address": "network",
"file_name": "file"
}

# combine all the MISP fields from fieldmap into one big list
mispattributes = {
"input": list(fieldmap.keys())
}


def handler(q=False):
"""
Convert a MISP query into a CSV file matching the ThreatConnect Structured Import file format.
Input
q: Query dictionary
"""
if q is False or not q:
return False

# Check if we were given a configuration
request = json.loads(q)
config = request.get("config", {"Default_Source": ""})
logging.info("Setting config to: %s", config)

for supportedType in fieldmap.keys():
if request.get(supportedType):
attrType = supportedType

if attrType:
eqlType = fieldmap[attrType]
event_type = event_types[eqlType]
fullEql = "{} where {} == \"{}\"".format(event_type, eqlType, request[attrType])
else:
misperrors['error'] = "Unsupported attributes type"
return misperrors

response = []
response.append({'types': ['comment'], 'categories': ['External analysis'], 'values': fullEql, 'comment': "Event EQL queries"})
return {'results': response}


def introspection():
"""
Relay the supported attributes to MISP.
No Input
Output
Dictionary of supported MISP attributes
"""
return mispattributes


def version():
"""
Relay module version and associated metadata to MISP.
No Input
Output
moduleinfo: metadata output containing all potential configuration values
"""
return moduleinfo
2 changes: 1 addition & 1 deletion misp_modules/modules/export_mod/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__all__ = ['cef_export', 'liteexport', 'goamlexport', 'threat_connect_export', 'pdfexport',
__all__ = ['cef_export', 'mass_eql_export', 'liteexport', 'goamlexport', 'threat_connect_export', 'pdfexport',
'threatStream_misp_export', 'osqueryexport', 'nexthinkexport']
99 changes: 99 additions & 0 deletions misp_modules/modules/export_mod/mass_eql_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""
Export module for converting MISP events into Endgame EQL queries
"""
import base64
import io
import json
import logging

misperrors = {"error": "Error"}

moduleinfo = {
"version": "0.1",
"author": "92 COS DOM",
"description": "Export MISP event in Event Query Language",
"module-type": ["export"]
}

# Map of MISP fields => Endgame fields
fieldmap = {
"ip-src": "source_address",
"ip-dst": "destination_address",
"filename": "file_name"
}

# Describe what events have what fields
event_types = {
"source_address": "network",
"destination_address": "network",
"file_name": "file"
}

# combine all the MISP fields from fieldmap into one big list
mispattributes = {
"input": list(fieldmap.keys())
}


def handler(q=False):
"""
Convert a MISP query into a CSV file matching the ThreatConnect Structured Import file format.
Input
q: Query dictionary
"""
if q is False or not q:
return False

# Check if we were given a configuration
request = json.loads(q)
config = request.get("config", {"Default_Source": ""})
logging.info("Setting config to: %s", config)

response = io.StringIO()

# start parsing MISP data
queryDict = {}
for event in request["data"]:
for attribute in event["Attribute"]:
if attribute["type"] in mispattributes["input"]:
logging.debug("Adding %s to EQL query", attribute["value"])
event_type = event_types[fieldmap[attribute["type"]]]
if event_type not in queryDict.keys():
queryDict[event_type] = {}
queryDict[event_type][attribute["value"]] = fieldmap[attribute["type"]]
i = 0
for query in queryDict.keys():
response.write("{} where\n".format(query))
for value in queryDict[query].keys():
if i != 0:
response.write(" or\n")
response.write("\t{} == \"{}\"".format(queryDict[query][value], value))
i += 1

return {"response": [], "data": str(base64.b64encode(bytes(response.getvalue(), 'utf-8')), 'utf-8')}


def introspection():
"""
Relay the supported attributes to MISP.
No Input
Output
Dictionary of supported MISP attributes
"""
modulesetup = {
"responseType": "application/txt",
"outputFileExtension": "txt",
"userConfig": {},
"inputSource": []
}
return modulesetup


def version():
"""
Relay module version and associated metadata to MISP.
No Input
Output
moduleinfo: metadata output containing all potential configuration values
"""
return moduleinfo