Mimecast is an email security and management platform that protects emails against cyber threats such as malware, phishing, and spam. Email remains one of the most prevalent attack vectors for cybercriminals seeking to infiltrate organizations and spread malware. Its widespread use makes it a top target for various malicious activities. Mimecast provides organizations with features like email filtering, data loss prevention (DLP), encryption, and archiving.
Wazuh is a free and open source SIEM and XDR platform that offers protection against security threats for various platforms including virtualized, cloud, and containerized environments.
In this blog post, we show the integration of Mimecast with Wazuh. This offers security analysts enhanced visibility into email-related threats by creating custom rules to alert on events of interest and show trends in certain malicious activities.
Requirements
We use the following infrastructure to demonstrate the integration of Mimecast with Wazuh:
- Wazuh 4.7.4 central components (Wazuh server, Wazuh indexer, Wazuh dashboard) installed using the Quickstart guide on an Ubuntu server.
- A Mimecast workspace and a user with administrator privileges to create API credentials.
Configuration
Follow the steps below to integrate Mimecast with Wazuh.
Mimecast web user interface
Enable logging
Follow the steps below to enable logging for your organization on your Mimecast account.
1. Login into the Mimecast administration console and navigate to Administration > Account > Account Settings to display the Account Settings page.
2. Select Enhanced Logging.
3. Select the types of logs you want to enable. The choices are:
- Inbound – logs for messages from external senders to internal recipients.
- Outbound – logs for messages from internal senders to external recipients.
- Internal – logs for messages between internal domains.
4. Select Save to apply the changes.
Once these settings are saved, Mimecast will start logging email transactions in your organization.
Note: It might take up to 30 minutes before the logs become available.
Configuring authentication and authorization
Mimecast provides the /api/audit/get-siem-logs API endpoint to facilitate the download of logs. Follow the Mimecast documentation on Authentication (Scripts and Server Apps) to generate the following values required to authenticate to the /api/audit/get-siem-logs API endpoint:
- APPLICATION_ID: The unique ID that identifies the application created in the Mimecast web user interface to pull logs from your account.
- APPLICATION_KEY: A secret used to authenticate and authorize the created application.
- ACCESS_KEY: The unique identifier that specifies the API user created in your mimecast account.
- SECRET_KEY: This is a shared secret between the script and the Mimecast authorization server.
Wazuh server
The following steps describe how to create a script that retrieves logs from the Mimecast API endpoint. We also create custom decoders and rules to trigger alerts when events of interest are captured by Mimecast.
Follow the steps below to configure the Wazuh server for log collection from Mimecast.
1. Create a Python script at /var/ossec/integrations/mimecast.py to connect to the Mimecast API and retrieve logs. The file /var/log/mimecast/mimecast.log is created upon execution of the script to store the retrieved Mimecast logs.
Replace the <APPLICATION_ID>, <APPLICATION_KEY>, <ACCESS_KEY>, <BASE_URL>, and <SECRET_KEY> variables with the appropriate values retrieved in configuring authentication and authorization above.
The <BASE_URL> refers to your Mimecast region, for example, https://eu-api.mimecast.com for the EU region. Visit the Global Base URLs reference guide for a list of Mimecast URLs.
Warning: We recommend you use a secret management solution to store the value of the variables instead of hardcoding them in the script.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Mimecast SIEM logs download
import logging.handlers
import json
import os
import requests
import base64
import uuid
import datetime
import hashlib
import shutil
import hmac
import time
from zipfile import ZipFile
import io
from logging.handlers import RotatingFileHandler
# Set up variables
APP_ID = "<APPLICATION_ID>"
APP_KEY = "<APPLICATION_KEY>"
ACCESS_KEY = '<ACCESS_KEY>'
SECRET_KEY = '<SECRET_KEY>'
base_url = "<BASE_URL>"
LOG_FILE_PATH = "/var/log/mimecast/log"
CHK_POINT_DIR = '/var/log/mimecast'
URI = "/api/audit/get-siem-logs"
# delete files after fetching
delete_files = False
# Set threshold in number of files in log file directory
log_file_threshold = 105
# Set up logging
log = logging.getLogger(__name__)
log.root.setLevel(logging.DEBUG)
log_formatter = logging.Formatter('%(levelname)s %(message)s')
log_handler = logging.StreamHandler()
log_handler.setFormatter(log_formatter)
log.addHandler(log_handler)
# Supporting methods
def rotate_file_if_needed(file_path, max_size_bytes):
if os.path.exists(file_path):
file_size = os.path.getsize(file_path)
if file_size >= max_size_bytes:
base_dir = os.path.dirname(file_path)
base_name = os.path.basename(file_path)
file_name, file_ext = os.path.splitext(base_name)
new_file_name = f"{file_name}_1{file_ext}"
new_file_path = os.path.join(base_dir, new_file_name)
shutil.move(file_path, new_file_path)
log.info(f"Rotated file: {file_path} -> {new_file_path}")
else:
log.warning(f"File not found: {file_path}")
def get_hdr_date():
return datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S UTC")
def read_file(file_name):
try:
with open(file_name, 'r') as f:
data = f.read()
return data
except Exception as e:
log.error('Error reading file ' + file_name + '. Cannot continue. Exception: ' + str(e))
quit()
def write_file(file_name, data_to_write):
if '.zip' in file_name:
try:
byte_content = io.BytesIO(data_to_write)
zip_file = ZipFile(byte_content)
zip_file.extractall(LOG_FILE_PATH)
except Exception as e:
log.error('Error writing file ' + file_name + '. Cannot continue. Exception: ' + str(e))
quit()
else:
try:
with open(file_name, 'w') as f:
f.write(data_to_write)
except Exception as e:
log.error('Error writing file ' + file_name + '. Cannot continue. Exception: ' + str(e))
quit()
def post_request(base_url, uri, post_body, access_key, secret_key):
request_id = str(uuid.uuid4())
request_date = get_hdr_date()
unsigned_auth_header = '{date}:{req_id}:{uri}:{app_key}'.format(
date=request_date,
req_id=request_id,
uri=uri,
app_key=APP_KEY
)
hmac_sha1 = hmac.new(
base64.b64decode(secret_key),
unsigned_auth_header.encode(),
digestmod=hashlib.sha1).digest()
sig = base64.encodebytes(hmac_sha1).rstrip()
headers = {
'Authorization': 'MC ' + access_key + ':' + sig.decode(),
'x-mc-app-id': APP_ID,
'x-mc-date': request_date,
'x-mc-req-id': request_id,
'Content-Type': 'application/json'
}
try:
log.debug('Sending request to ' + base_url + uri + ' with request Id: ' + request_id)
r = requests.post(url=base_url + uri, data=json.dumps(post_body), headers=headers)
if r.status_code == 429:
log.warning('Rate limit hit. Sleeping for ' + str(r.headers['X-RateLimit-Reset'] * 1000))
time.sleep(r.headers['X-RateLimit-Reset'] * 1000)
r = requests.post(url=base_url + uri, data=json.dumps(post_body), headers=headers)
except Exception as e:
log.error('Unexpected error connecting to API. Exception: ' + str(e))
return 'error'
if r.status_code != 200:
log.error('Request to ' + uri + ' with , request id: ' + request_id + ' returned with status code: ' +
str(r.status_code) + ', response body: ' + r.text)
return 'error'
return r.content, r.headers
def get_mta_siem_logs(checkpoint_dir, base_url, access_key, secret_key, now):
uri = "/api/audit/get-siem-logs"
checkpoint_filename = os.path.join(checkpoint_dir, 'get_mta_siem_logs_checkpoint')
post_body = dict()
post_body['data'] = [{}]
post_body['data'][0]['type'] = 'MTA'
post_body['data'][0]['compress'] = True
if os.path.exists(checkpoint_filename):
post_body['data'][0]['token'] = read_file(checkpoint_filename)
resp = post_request(base_url, uri, post_body, access_key, secret_key)
if resp != 'error':
resp_body = resp[0]
resp_headers = resp[1]
content_type = resp_headers['Content-Type']
if content_type == 'application/json':
log.info('No more logs available')
return False
elif content_type == 'application/octet-stream':
file_name = resp_headers['Content-Disposition'].split('=\"')
file_name = file_name[1][:-1]
write_file(os.path.join(LOG_FILE_PATH, file_name), resp_body)
write_file(checkpoint_filename, resp_headers['mc-siem-token'])
return True
else:
log.error('Unexpected response')
for header in resp_headers:
log.error(header)
return False
def run_script():
try:
log.info('Getting MTA log data')
# Rotate merged log file if needed before downloading new logs
rotate_file_if_needed(os.path.join(LOG_FILE_PATH, 'mimecast.log'), 5242880)
get_mta_siem_logs(checkpoint_dir=CHK_POINT_DIR, base_url=base_url, access_key=ACCESS_KEY,
secret_key=SECRET_KEY, now=time.time())
except Exception as e:
log.error('Unexpected error getting MTA logs ' + str(e))
files = [os.path.join(LOG_FILE_PATH, f) for f in os.listdir(LOG_FILE_PATH)]
files.sort(key=os.path.getctime)
if delete_files or len(files) >= log_file_threshold:
num_files_to_delete = len(files) - log_file_threshold
for i in range(num_files_to_delete):
try:
os.unlink(files[i])
except Exception as e:
log.error('Failed to delete file {}. Reason: {}'.format(files[i], e))
continue
merged_file_path = os.path.join(LOG_FILE_PATH, 'mimecast.log')
with open(merged_file_path, 'a') as merged_file:
for filename in os.listdir(LOG_FILE_PATH):
if filename.endswith('.siem') and filename != 'mimecast.log':
file_path = os.path.join(LOG_FILE_PATH, filename)
try:
with open(file_path, 'r') as log_file:
for line in log_file:
merged_file.write(line)
except Exception as e:
log.error('Failed to merge log file {}. Reason: {}'.format(file_path, e))
os.remove(file_path)
run_script()
2. Set the ownership and permissions for the /var/ossec/integrations/mimecast.py file. This ensures the script is only available to the root user and wazuh group by granting them full permissions, read and execute access respectively:
# chown root:wazuh /var/ossec/integrations/mimecast.py # chmod 750 /var/ossec/integrations/mimecast.py
3. Add the following configuration to the <ossec_config> block of the /var/ossec/etc/ossec.conf local configuration file to automate the execution of the script. We also configure the Wazuh Logcollector module to monitor the /var/log/mimecast/log/mimecast.log file for new logs:
<wodle name="command"> <disabled>no</disabled> <command>/var/ossec/framework/python/bin/python3 /var/ossec/integrations/mimecast.py</command> <interval>5m</interval> <ignore_output>yes</ignore_output> <run_on_start>yes</run_on_start> <timeout>120</timeout> </wodle> <localfile> <log_format>syslog</log_format> <location>/var/log/mimecast/log/mimecast.log</location> </localfile>
Note: The <interval> tag specifies the interval between execution of the script.
If you already have logs enabled on your Mimecast account, the script will retrieve the earliest available logs on your account. Mimecast keeps your logs for up to 7 days.
Custom decoders
1. Create a decoder file /var/ossec/etc/decoders/mimecast_decoders.xml and add the following decoders:
<!-- Mimecast SIEM Logs --> <decoder name="mimecast"> <prematch type="pcre2">datetime=.*\|aCode=</prematch> </decoder> <decoder name="mimecast"> <prematch type="pcre2">datetime=.*\|acc=</prematch> </decoder> <decoder name="mimecast"> <prematch type="pcre2">datetime=.*Mimecast</prematch> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)datetime=(?:\\)?([^|]+)</regex> <order>mimecast.datetime</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)aCode=(?:\\)?([^|]+)</regex> <order>mimecast.aCode</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)acc=(?:\\)?([^|]+)</regex> <order>mimecast.acc</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)IP=(?:\\)?([^|]+)</regex> <order>mimecast.IP</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)RejType=(?:\\)?([^|]+)</regex> <order>mimecast.RejType</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Error=(?:\\)?([^|]+)</regex> <order>mimecast.Error</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)RejCode=(?:\\)?([^|]+)</regex> <order>mimecast.RejCode</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Dir=(?:\\)?([^|]+)</regex> <order>mimecast.Dir</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)headerFrom=(?:\\)?([^|]+)</regex> <order>mimecast.headerFrom</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Sender=(?:\\)?([^|]+)</regex> <order>mimecast.Sender</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Rcpt=(?:\\)?([^|]+)</regex> <order>mimecast.Rcpt</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Act=(?:\\)?([^|]+)</regex> <order>mimecast.Act</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)RejInfo=(?:\\)?([^|]+)</regex> <order>mimecast.RejInfo</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)TlsVer=(?:\\)?([^|]+)</regex> <order>mimecast.TlsVer</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Cphr=(?:\\)?([^|]+)</regex> <order>mimecast.Cphr</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Hld=(?:\\)?([^|]+)</regex> <order>mimecast.Hld</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)AttSize=(?:\\)?([^|]+)</regex> <order>mimecast.AttSize</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)IPNewDomain=(?:\\)?([^|]+)</regex> <order>mimecast.IPNewDomain</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)IPReplyMismatch=(?:\\)?([^|]+)</regex> <order>mimecast.IPReplyMismatch</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)AttCnt=(?:\\)?([^|]+)</regex> <order>mimecast.AttCnt</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)IPInternalName=(?:\\)?([^|]+)</regex> <order>mimecast.IPInternalName</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)AttNames=(?:\\)?([^|]+)</regex> <order>mimecast.AttNames</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)MsgSize=(?:\\)?([^|]+)</regex> <order>mimecast.MsgSize</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)MsgId=(?:\\)?([^|]+)</regex> <order>mimecast.MsgId</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)IPThreadDict=(?:\\)?([^|]+)</regex> <order>mimecast.IPThreadDict</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)IPSimilarDomain=(?:\\)?([^|]+)</regex> <order>mimecast.IPSimilarDomain</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Delivered=(?:\\)?([^|]+)</regex> <order>mimecast.Delivered</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Err=(?:\\)?([^|]+)</regex> <order>mimecast.Err</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)ReceiptAck=(?:\\)?([^|]+)</regex> <order>mimecast.ReceiptAck</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Subject=(?:\\)?([^|]+)</regex> <order>mimecast.Subject</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Attempt=(?:\\)?([^|]+)</regex> <order>mimecast.Attempt</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Snt=(?:\\)?([^|]+)</regex> <order>mimecast.Snt</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)UseTls=(?:\\)?([^|]+)</regex> <order>mimecast.UseTls</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)MimecastIP=(?:\\)?([^|]+)</regex> <order>mimecast.MimecastIP</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)fileName=(?:\\)?([^|]+)</regex> <order>mimecast.fileName</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)sha256=(?:\\)?([^|]+)</regex> <order>mimecast.sha256</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Size=(?:\\)?([^|]+)</regex> <order>mimecast.Size</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Recipient=(?:\\)?([^|]+)</regex> <order>mimecast.Recipient</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)SenderDomain=(?:\\)?([^|]+)</regex> <order>mimecast.SenderDomain</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)fileExt=(?:\\)?([^|]+)</regex> <order>mimecast.fileExt</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Virus=(?:\\)?([^|]+)</regex> <order>mimecast.Virus</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)sha1=(?:\\)?([^|]+)</regex> <order>mimecast.sha1</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)SenderDomainInternal=(?:\\)?([^|]+)</regex> <order>mimecast.SenderDomainInternal</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)fileMime=(?:\\)?([^|]+)</regex> <order>mimecast.fileMime</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)CustomerIP=(?:\\)?([^|]+)</regex> <order>mimecast.CustomerIP</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Route=(?:\\)?([^|]+)</regex> <order>mimecast.Route</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)md5=(?:\\)?([^|]+)</regex> <order>mimecast.md5</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)SourceIP=(?:\\)?([^|]+)</regex> <order>mimecast.SourceIP</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)UrlCategory=(?:\\)?([^|]+)</regex> <order>mimecast.UrlCategory</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)ScanResultInfo=(?:\\)?([^|]+)</regex> <order>mimecast.ScanResultInfo</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)URL=(?:\\)?([^|]+)</regex> <order>mimecast.URL</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Receipient=(?:\\)?([^|]+)</regex> <order>mimecast.Receipient</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Definition=(?:\\)?([^|]+)</regex> <order>mimecast.Definition</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Hits=(?:\\)?([^|]+)</regex> <order>mimecast.Hits</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)Action=(?:\\)?([^|]+)</regex> <order>mimecast.Action</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)TaggedExternal=(?:\\)?([^|]+)</regex> <order>mimecast.TaggedExternal</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)TaggedMalicious=(?:\\)?([^|]+)</regex> <order>mimecast.TaggedMalicious</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)InternalName=(?:\\)?([^|]+)</regex> <order>mimecast.InternalName</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)CustomName=(?:\\)?([^|]+)</regex> <order>mimecast.CustomName</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)NewDomain=(?:\\)?([^|]+)</regex> <order>mimecast.NewDomain</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)SimilarInternalDomain=(?:\\)?([^|]+)</regex> <order>mimecast.SimilarInternalDomain</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)SimilarCustomExternalDomain=(?:\\)?([^|]+)</regex> <order>mimecast.SimilarCustomExternalDomain</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)SimilarMimecastExternalDomain=(?:\\)?([^|]+)</regex> <order>mimecast.SimilarMimecastExternalDomain</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)ReplyMismatch=(?:\\)?([^|]+)</regex> <order>mimecast.ReplyMismatch</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)ThreatDictionary=(?:\\)?([^|]+)</regex> <order>mimecast.ThreatDictionary</order> </decoder> <decoder name="mimecast-siem-logs"> <parent>mimecast</parent> <regex type="pcre2">(?i)reason=(?:\\)?([^|]+)</regex> <order>mimecast.reason</order> </decoder>
Custom rules
1. Create a rule file /var/ossec/etc/rules/mimecast_rules.xml and add the following rules:
<!-- Rules for Mimecast via API -->
<!-- Mimecast SIEM Logs -->
<!-- Mimecast logs grouped -->
<group name="mimecast">
<rule id="106000" level="2">
<field name="mimecast.datetime">\.</field>
<description>Logs from Mimecast.</description>
</rule>
<!-- Rule to detect mail held for admin review -->
<rule id="106001" level="5">
<if_sid>106000</if_sid>
<field name="mimecast.Act">Hld</field>
<description>Message $(mimecast.MsgId) held for review.</description>
<mitre>
<id>T1566</id>
</mitre>
</rule>
<!-- Rule to detect AV logs -->
<rule id="106002" level="5">
<if_sid>106000</if_sid>
<field name="mimecast.Virus">\.</field>
<field name="mimecast.Subject">\.</field>
<description>Malicious email with category "$(mimecast.Virus)" sent to $(mimecast.Recipient).</description>
<mitre>
<id>T1598.003</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106003" level="10" frequency="3" timeframe="300">
<if_matched_sid>106002</if_matched_sid>
<same_field>mimecast.Sender</same_field>
<description>Multiple malicious emails received from same sender $(mimecast.Sender).</description>
<mitre>
<id>T1598.003</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106004" level="10" frequency="5" timeframe="300">
<if_matched_sid>106002</if_matched_sid>
<same_field>mimecast.Sender</same_field>
<different_field>mimecast.Recipient</different_field>
<description>Malicious emails received by multiple users from same sender $(mimecast.Sender).</description>
<mitre>
<id>T1598.003</id>
<id>T1114</id>
</mitre>
</rule>
<!-- Rules to detect Target Threat Protection - Internal Email Protect logs -->
<rule id="106005" level="3">
<if_sid>106000</if_sid>
<field name="mimecast.ScanResultInfo">Blocked</field>
<description>User $(mimecast.Recipient) blocked from clicking a malicious/blocked link $(URL).</description>
<mitre>
<id>T1566.002</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106006" level="10" frequency="3" timeframe="300">
<if_matched_sid>106005</if_matched_sid>
<different_field>mimecast.Recipient</different_field>
<same_field>mimecast.URL</same_field>
<description>Multiple users trying to access same malicious/blocked link $(URL).</description>
<mitre>
<id>T1566.002</id>
<id>T1114</id>
</mitre>
</rule>
<!-- Rules to detect Targeted Threat Protection - Impersonation Protect logs -->
<rule id="106007" level="5">
<if_sid>106000</if_sid>
<field name="mimecast.Definition">Impersonation</field>
<description>Internal user $(mimecast.Sender) has been impersonated.</description>
<mitre>
<id>T1036</id>
<id>T1586.002</id>
<id>T1566</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106008" level="5">
<if_sid>106007</if_sid>
<field name="mimecast.ReplyMismatch">true</field>
<description>Reply address mismatch: Reply address does not correspond to the senders address.</description>
<mitre>
<id>T1036</id>
<id>T1586.002</id>
<id>T1566</id>
<id>T1114</id>
</mitre>
</rule>
<!-- Rules to detect Targeted Threat Protection - URL Protect logs -->
<rule id="106009" level="4">
<if_sid>106000</if_sid>
<field name="mimecast.reason">malicious</field>
<field name="mimecast.URL">\.</field>
<field name="mimecast.urlCategory">Blocked</field>
<description>User $(mimecast.Recipient) blocked from clicking a malicious link $(URL).</description>
<mitre>
<id>T1566.002</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106010" level="10" frequency="3" timeframe="300">
<if_matched_sid>106009</if_matched_sid>
<different_field>mimecast.Recipient</different_field>
<description>Multiple users trying to access same malicious/blocked link $(URL).</description>
<mitre>
<id>T1566.002</id>
<id>T1114</id>
</mitre>
</rule>
<!-- Rule to detect Targeted Threat Protection - Attachment Protect logs -->
<rule id="106011" level="10">
<if_sid>106000</if_sid>
<field name="mimecast.fileName">\.</field>
<field name="mimecast.fileMime">\.</field>
<field name="mimecast.sha256">\.</field>
<match negate="yes">Subject</match>
<description>Mimecast sandbox has detected a potentially malicious file $(mimecast.fileName).$(mimecast.fileExt) on $(mimecast.Recipient).</description>
<mitre>
<id>T1204.002</id>
<id>T1598.002</id>
<id>T1566.001</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106012" level="10" frequency="3" timeframe="300">
<if_matched_sid>106011</if_matched_sid>
<same_field>mimecast.Sender</same_field>
<description>Multiple potentially malicious files received from same sender $(mimecast.Sender).</description>
<mitre>
<id>T1204.002</id>
<id>T1598.002</id>
<id>T1566.001</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106013" level="10" frequency="3" timeframe="300">
<if_matched_sid>106011</if_matched_sid>
<same_field>mimecast.IP</same_field>
<description>Multiple potentially malicious files received from same source $(mimecast.IP).</description>
<mitre>
<id>T1204.002</id>
<id>T1598.002</id>
<id>T1566.001</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106014" level="10" frequency="4" timeframe="300">
<if_matched_sid>106011</if_matched_sid>
<same_field>mimecast.sha256</same_field>
<description>Same potentially malicious file $(mimecast.fileName) detected on multiple recipients.</description>
<mitre>
<id>T1204.002</id>
<id>T1598.002</id>
<id>T1566.001</id>
<id>T1114</id>
</mitre>
</rule>
<rule id="106015" level="10" frequency="3" timeframe="300">
<if_matched_sid>106011</if_matched_sid>
<same_field>mimecast.SenderDomain</same_field>
<description>Multiple potentially malicious files received from same domain.</description>
<mitre>
<id>T1204.002</id>
<id>T1598.002</id>
<id>T1566.001</id>
<id>T1114</id>
</mitre>
</rule>
</group>
Where:
- Rule ID
100600groups all Mimecast events. - Rule ID
106001detects emails held for admin review. - Rule IDs
106002,106003, and106004detect email antivirus events. - Rule IDs
106005and106006detect internal email protection events. - Rule IDs
106007and106008detect impersonation protection events. - Rule IDs
106009and106010detect URL protection events. - Rule IDs
106011,106012,106013,106014, and106015detect email attachment protection events.
2. Restart the Wazuh manager to apply the changes:
# systemctl restart wazuh-manager
Visualizing alerts
When a Mimecast event that matches any of our custom rules occurs, we see alerts on the Wazuh dashboard. Navigate to Modules > Security events to view the alerts.





Conclusion
In this blog post, we demonstrated how to integrate Mimecast with Wazuh. This integration helps to streamline your security monitoring activities by offering a unified view of your email security events. It also gives administrators and security analysts deeper insights into email security events.
Wazuh is a free and open source SIEM and XDR solution. Wazuh can be deployed and managed on-premises or on the Wazuh cloud. Check out our community for support and updates.
References