mirror of https://github.com/MISP/mail_to_misp
initial commit
commit
97e5dddc61
|
@ -0,0 +1 @@
|
|||
/Users/rommelfs/Library/Application Scripts/com.apple.mail/MISP Mail Rule Action.scptd
|
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import urlmarker
|
||||
import sys
|
||||
import re
|
||||
from pyfaup.faup import Faup
|
||||
from pymisp import PyMISP
|
||||
from defang import refang
|
||||
import dns.resolver
|
||||
import mail_to_misp_config as config
|
||||
|
||||
debug = config.debug
|
||||
if debug:
|
||||
debug_out_file = config.debug_out_file
|
||||
target = open(debug_out_file, 'w')
|
||||
target.write("New debug session opened")
|
||||
try:
|
||||
email_data = str(sys.argv[1])
|
||||
email_subject = str(sys.argv[2])
|
||||
except:
|
||||
if debug:
|
||||
target.write("FATAL ERROR: Not all required input received")
|
||||
sys.exit(1)
|
||||
|
||||
if debug:
|
||||
target.write(email_subject)
|
||||
target.write(email_data)
|
||||
|
||||
misp_url = config.misp_url
|
||||
misp_key = config.misp_key
|
||||
misp_verifycert = config.misp_verifycert
|
||||
|
||||
resolver = dns.resolver.Resolver(configure=False)
|
||||
resolver.nameservers = config.nameservers
|
||||
|
||||
excludelist = config.excludelist
|
||||
externallist = config.externallist
|
||||
|
||||
malwaretags = config.malwaretags
|
||||
dependingtags = config.dependingtags
|
||||
|
||||
# Ignore lines in body of message
|
||||
email_data = re.sub(".*From: .*\n?","", email_data)
|
||||
email_data = re.sub(".*Sender: .*\n?","", email_data)
|
||||
email_data = re.sub(".*Sender IP: .*\n?","", email_data)
|
||||
email_data = re.sub(".*Reply-To: .*\n?","", email_data)
|
||||
email_data = re.sub(".*Registrar WHOIS Server: .*\n?","", email_data)
|
||||
email_data = re.sub(".*Registrar: .*\n?","", email_data)
|
||||
email_data = re.sub(".*Domain Status: .*\n?","", email_data)
|
||||
email_data = re.sub(".*Registrant Email: .*\n?","", email_data)
|
||||
email_data = re.sub(".*IP Location: .*\n?","", email_data)
|
||||
|
||||
# Remove tags from subject
|
||||
email_subject = re.sub("[\(\[].*?[\)\]]", "", email_subject)
|
||||
# Remove "Re: " from subject
|
||||
email_subject = re.sub("Re: ", "", email_subject)
|
||||
|
||||
|
||||
def init(url, key):
|
||||
return PyMISP(url, key, misp_verifycert, 'json')
|
||||
|
||||
# Evaluate classification
|
||||
tlptags = config.tlptags
|
||||
for tag in tlptags:
|
||||
for alternativetag in tlptags[tag]:
|
||||
if alternativetag in email_data.lower():
|
||||
tlp_tag = tag
|
||||
|
||||
# Create the MISP event
|
||||
misp = init(misp_url, misp_key)
|
||||
new_event = misp.new_event(info=email_subject, distribution=0, threat_level_id=3, analysis=1)
|
||||
misp.add_tag(new_event, tlp_tag)
|
||||
|
||||
# Add additional tags depending on others
|
||||
for tag in dependingtags:
|
||||
if tag in tlp_tag:
|
||||
for dependingtag in dependingtags[tag]:
|
||||
misp.add_tag(new_event, dependingtag)
|
||||
|
||||
# Extract IOCs
|
||||
email_data = refang(email_data)
|
||||
urllist = re.findall(urlmarker.WEB_URL_REGEX,email_data)
|
||||
urllist += re.findall(urlmarker.IP_REGEX,email_data)
|
||||
if debug:
|
||||
target.write(str(urllist))
|
||||
|
||||
# Init Faup
|
||||
f = Faup()
|
||||
|
||||
for malware in malwaretags:
|
||||
if malware in email_subject.lower():
|
||||
for tag in malwaretags[malware]:
|
||||
misp.add_tag(new_event, tag)
|
||||
|
||||
# Add IOCs and expanded information to MISP
|
||||
for entry in urllist:
|
||||
f.decode(entry)
|
||||
domainname = f.get_domain().lower()
|
||||
if debug:
|
||||
target.write(domainname + "\n")
|
||||
if domainname not in excludelist:
|
||||
if domainname in externallist:
|
||||
misp.add_named_attribute(new_event, 'link', entry, category='External analysis', to_ids=False)
|
||||
else:
|
||||
if debug:
|
||||
target.write(entry + "\n")
|
||||
misp.add_url(new_event, entry, category='Network activity', to_ids=True)
|
||||
hostname = f.get_host().lower()
|
||||
if debug:
|
||||
target.write(hostname + "\n")
|
||||
port = f.get_port()
|
||||
comment = ""
|
||||
if port:
|
||||
comment = "on port: " + str(port)
|
||||
misp.add_hostname(new_event, hostname, comment=comment, category='Network activity', to_ids=True)
|
||||
try:
|
||||
for rdata in dns.resolver.query(hostname, 'A'):
|
||||
if debug:
|
||||
target.write(str(rdata) + "\n")
|
||||
misp.add_ipdst(new_event, str(rdata), category='Network activity', to_ids=True, comment=hostname)
|
||||
except:
|
||||
if debug:
|
||||
target.write("DNS unsuccessful\n")
|
||||
if debug:
|
||||
target.close()
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
misp_url = 'YOUR_MISP_URL'
|
||||
misp_key = 'YOUR_KEY_HERE' # The MISP auth key can be found on the MISP web interface under the automation section
|
||||
misp_verifycert = True
|
||||
|
||||
debug = True
|
||||
debug_out_file = '/tmp/mail_to_misp-debug.txt'
|
||||
nameservers = ['149.13.33.69']
|
||||
|
||||
excludelist = ('google.com', 'microsoft.com')
|
||||
externallist = ('virustotal.com', 'malwr.com', 'hybrid-analysis.com', 'emergingthreats.net')
|
||||
|
||||
# TLP tag setup
|
||||
# Tuples contain different variations of spelling
|
||||
tlptags = { 'tlp:white': [ 'tlp:white', 'tlp: white' ],
|
||||
'tlp:green': [ 'tlp:green', 'tlp: green' ],
|
||||
'tlp:amber': [ 'tlp:amber', 'tlp: amber' ]
|
||||
}
|
||||
|
||||
malwaretags = { 'locky': [ 'ecsirt:malicious-code="ransomware"', 'misp-galaxy:ransomware="Locky"' ],
|
||||
'dridex': [ 'misp-galaxy:tool="dridex"' ],
|
||||
'netwire': [ 'Netwire RAT' ]
|
||||
}
|
||||
# Tags to be set depending on the presence of other tags
|
||||
dependingtags = { 'tlp:white': [ 'circl:osint-feed' ]
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
url matching regex
|
||||
http://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
The regex patterns in this gist are intended to match any URLs,
|
||||
including "mailto:foo@example.com", "x-whatever://foo", etc. For a
|
||||
pattern that attempts only to match web URLs (http, https), see:
|
||||
https://gist.github.com/gruber/8891611
|
||||
"""
|
||||
ANY_URL_REGEX = r"""(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))"""
|
||||
|
||||
"""
|
||||
The regex patterns in this gist are intended only to match web URLs -- http,
|
||||
https, and naked domains like "example.com". For a pattern that attempts to
|
||||
match all URLs, regardless of protocol, see: https://gist.github.com/gruber/249502
|
||||
"""
|
||||
WEB_URL_REGEX = r"""(?i)\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)\b/?(?!@)))"""
|
||||
|
||||
IP_REGEX = r"""[0-9]+(?:\.[0-9]+){3}:[0-9]+"""
|
Loading…
Reference in New Issue