detect: add email.body_md5 keyword

email.body_md5 matches on md5 hash generated from email body
This keyword maps to the EVE field email.body_md5
It is a sticky buffer
Supports prefiltering

Ticket: #7587
pull/13878/head
Alice Akaki 2 years ago committed by Victor Julien
parent 6c88cc1e0c
commit 8e0b0ef35f

@ -222,3 +222,29 @@ Example of a signature that would alert if a packet contains the MIME field ``re
.. container:: example-rule
alert smtp any any -> any any (msg:"Test mime email received"; :example-rule-emphasis:`email.received; content:"from [65.201.218.30] (helo=COZOXORY.club)by 173-66-46-112.wash.fios.verizon.net with esmtpa (Exim 4.86)(envelope-from )id 71cF63a9for mirjam@abrakadabra.ch\; Mon, 29 Jul 2019 17:01:45 +0000";` sid:1;)
email.body_md5
--------------
Matches the ``md5`` hash generated from an email body.
This keyword only works if config option
``app-layer.protocols.smtp.mime.body-md5`` is enabled or auto.
It should be used with ``requires: keyword email.body_md5;``
Syntax::
email.body_md5; content:"<content to match against>";
``email.body_md5`` is a 'sticky buffer' and can be used as a ``fast_pattern``.
This keyword maps to the EVE field ``email.body_md5``.
Example
^^^^^^^
Example of a signature that would alert if the hash ``ed00c81b85fa455d60e19f1230977134``
is generated from an email body:
.. container:: example-rule
alert smtp any any -> any any (msg:"Test mime email body_md5"; :example-rule-emphasis:`requires: keyword email.body_md5; email.body_md5; content:"ed00c81b85fa455d60e19f1230977134";` sid:1;)

@ -93,3 +93,12 @@ pub unsafe extern "C" fn SCDetectMimeEmailGetDataArray(
}
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn SCDetectMimeEmailGetBodyMd5(
ctx: &MimeStateSMTP, buffer: *mut *const u8, buffer_len: *mut u32,
) {
let hash = &ctx.md5_result;
*buffer = hash.as_ptr();
*buffer_len = hash.len() as u32;
}

@ -375,7 +375,7 @@ fn mime_smtp_parse_line(
let mut warnings = 0;
match ctx.state_flag {
MimeSmtpParserState::MimeSmtpStart => {
if unsafe { MIME_SMTP_CONFIG_BODY_MD5 }
if unsafe { MIME_SMTP_CONFIG_ENABLE_BODY_MD5 }
&& ctx.md5_state != MimeSmtpMd5State::MimeSmtpMd5Started
{
ctx.md5 = Md5::new();
@ -710,7 +710,8 @@ pub unsafe extern "C" fn SCMimeSmtpGetHeaderName(
static mut MIME_SMTP_CONFIG_DECODE_BASE64: bool = true;
static mut MIME_SMTP_CONFIG_DECODE_QUOTED: bool = true;
static mut MIME_SMTP_CONFIG_BODY_MD5: bool = false;
static mut MIME_SMTP_CONFIG_ENABLE_BODY_MD5: bool = false;
static mut MIME_SMTP_CONFIG_DISABLE_BODY_MD5: bool = false;
static mut MIME_SMTP_CONFIG_HEADER_VALUE_DEPTH: u32 = 0;
static mut MIME_SMTP_CONFIG_EXTRACT_URLS: bool = true;
static mut MIME_SMTP_CONFIG_LOG_URL_SCHEME: bool = false;
@ -737,8 +738,22 @@ pub unsafe extern "C" fn SCMimeSmtpConfigLogUrlScheme(val: std::os::raw::c_int)
}
#[no_mangle]
pub unsafe extern "C" fn SCMimeSmtpConfigBodyMd5(val: std::os::raw::c_int) {
MIME_SMTP_CONFIG_BODY_MD5 = val != 0;
pub unsafe extern "C" fn SCMimeSmtpConfigBodyMd5(val: bool) {
if val {
MIME_SMTP_CONFIG_ENABLE_BODY_MD5 = true;
} else {
MIME_SMTP_CONFIG_DISABLE_BODY_MD5 = true;
}
}
#[no_mangle]
pub unsafe extern "C" fn MimeBodyMd5IsEnabled() -> bool {
MIME_SMTP_CONFIG_ENABLE_BODY_MD5
}
#[no_mangle]
pub unsafe extern "C" fn MimeBodyMd5IsDisabled() -> bool {
MIME_SMTP_CONFIG_DISABLE_BODY_MD5
}
#[no_mangle]

@ -391,9 +391,16 @@ static void SMTPConfigure(void) {
SCMimeSmtpConfigLogUrlScheme(val);
}
ret = SCConfGetChildValueBool(config, "body-md5", &val);
if (ret) {
SCMimeSmtpConfigBodyMd5(val);
// default (if value is absent) is auto : do not set anything
const char *strval;
if (SCConfGetChildValue(config, "body-md5", &strval) == 1) {
if (SCConfValIsFalse(strval)) {
SCMimeSmtpConfigBodyMd5(false);
} else if (SCConfValIsTrue(strval)) {
SCMimeSmtpConfigBodyMd5(true);
} else if (strcmp(strval, "auto") != 0) {
SCLogWarning("Unknown value for body-md5: %s", strval);
}
}
}

@ -33,6 +33,7 @@ static int g_mime_email_message_id_buffer_id = 0;
static int g_mime_email_x_mailer_buffer_id = 0;
static int g_mime_email_url_buffer_id = 0;
static int g_mime_email_received_buffer_id = 0;
static int g_mime_email_body_md5_buffer_id = 0;
static int DetectMimeEmailFromSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
@ -225,6 +226,36 @@ static bool GetMimeEmailReceivedData(DetectEngineThreadCtx *det_ctx, const void
return true;
}
int DETECT_EMAIL_BODY_MD5 = 0;
static int DetectMimeEmailBodyMd5Setup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (SCDetectBufferSetActiveList(de_ctx, s, g_mime_email_body_md5_buffer_id) < 0)
return -1;
if (SCDetectSignatureSetAppProto(s, ALPROTO_SMTP) < 0)
return -1;
if (!MimeBodyMd5IsEnabled()) {
// we registered the keyword if not explicitly disabled, so we are here in auto mode
SCMimeSmtpConfigBodyMd5(true);
}
return 0;
}
static bool GetMimeEmailBodyMd5Data(
const void *txv, const uint8_t _flow_flags, const uint8_t **data, uint32_t *data_len)
{
SMTPTransaction *tx = (SMTPTransaction *)txv;
if (tx->mime_state == NULL)
return false;
SCDetectMimeEmailGetBodyMd5(tx->mime_state, data, data_len);
return true;
}
void DetectEmailRegister(void)
{
SCSigTableAppLiteElmt kw = { 0 };
@ -309,4 +340,19 @@ void DetectEmailRegister(void)
SCDetectHelperKeywordRegister(&kw);
g_mime_email_received_buffer_id = SCDetectHelperMultiBufferMpmRegister("email.received",
"MIME EMAIL RECEIVED", ALPROTO_SMTP, STREAM_TOSERVER, GetMimeEmailReceivedData);
if (!MimeBodyMd5IsDisabled()) {
// do not register the keyword if explicitly disabled
kw.name = "email.body_md5";
kw.desc = "'md5' hash generated from an email body";
kw.url = "/rules/email-keywords.html#email.body_md5";
kw.Setup = DetectMimeEmailBodyMd5Setup;
kw.flags = SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
DETECT_EMAIL_BODY_MD5 = SCDetectHelperKeywordRegister(&kw);
// We do not need a progress because SMTP tx has only progress 0 or 1
// even if we have a MimeSmtpMd5State enumeration
g_mime_email_body_md5_buffer_id = SCDetectHelperBufferMpmRegister("email.body_md5",
"MIME EMAIL BODY MD5", ALPROTO_SMTP, STREAM_TOSERVER, GetMimeEmailBodyMd5Data);
DetectBufferTypeRegisterValidateCallback("email.body_md5", DetectMd5ValidateCallback);
}
}

@ -1039,7 +1039,9 @@ app-layer:
#log-url-scheme: yes
# Set to yes to compute the md5 of the mail body. You will then
# be able to journalize it.
body-md5: no
# Set it to no to disable it.
# Default is auto: not enabled until a rule needs it
# body-md5: auto
# Configure inspected-tracker for file_data keyword
inspected-tracker:
content-limit: 100000

Loading…
Cancel
Save