detect: add email.received keyword

email.received matches on MIME EMAIL Received
This keyword maps to the EVE field email.received[]
It is a sticky buffer
Supports multiple buffer matching
Supports prefiltering

Ticket: #7599
pull/13035/head
Alice Akaki 7 months ago committed by Victor Julien
parent deb761367d
commit bda0890834

@ -196,3 +196,29 @@ Example of a signature that would alert if an email contains the ``url`` ``test-
.. container:: example-rule
alert smtp any any -> any any (msg:"Test mime email url"; :example-rule-emphasis:`email.url; content:"test-site.org/blah/123/";` sid:1;)
email.received
--------------
Matches ``Received`` field of an email.
Comparison is case-sensitive.
Syntax::
email.received; content:"<content to match against>";
``email.received`` is a 'sticky buffer' and can be used as a ``fast_pattern``.
``email.received`` supports multiple buffer matching, see :doc:`multi-buffer-matching`.
This keyword maps to the EVE field ``email.received[]``
Example
^^^^^^^
Example of a signature that would alert if a packet contains the MIME field ``received`` with the value ``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``
.. 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;)

@ -77,6 +77,7 @@ following keywords:
* ``dns.answer.name``
* ``dns.query.name``
* ``dns.query``
* ``email.received``
* ``email.url``
* ``file.data``
* ``file.magic``

@ -60,3 +60,32 @@ pub unsafe extern "C" fn SCDetectMimeEmailGetUrl(
return 0;
}
/// Intermediary function used in detect-email.c to access data from the MimeStateSMTP structure
/// for array header fields.
/// The hname parameter determines which data will be returned.
#[no_mangle]
pub unsafe extern "C" fn SCDetectMimeEmailGetDataArray(
ctx: &MimeStateSMTP, buffer: *mut *const u8, buffer_len: *mut u32,
hname: *const std::os::raw::c_char, idx: u32,
) -> u8 {
let c_str = CStr::from_ptr(hname); //unsafe
let str = c_str.to_str().unwrap_or("");
let mut i = 0;
for h in &ctx.headers[..ctx.main_headers_nb] {
if mime::slice_equals_lowercase(&h.name, str.as_bytes()) {
if i == idx {
*buffer = h.value.as_ptr();
*buffer_len = h.value.len() as u32;
return 1;
}
i += 1;
}
}
*buffer = ptr::null();
*buffer_len = 0;
return 0;
}

@ -31,6 +31,7 @@ static int g_mime_email_date_buffer_id = 0;
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 DetectMimeEmailFromSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
@ -314,6 +315,46 @@ static InspectionBuffer *GetMimeEmailUrlData(DetectEngineThreadCtx *det_ctx,
return buffer;
}
static int DetectMimeEmailReceivedSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(de_ctx, s, g_mime_email_received_buffer_id) < 0)
return -1;
if (DetectSignatureSetAppProto(s, ALPROTO_SMTP) < 0)
return -1;
return 0;
}
static InspectionBuffer *GetMimeEmailReceivedData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv,
const int list_id, uint32_t idx)
{
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, idx);
if (buffer == NULL || buffer->initialized)
return buffer;
SMTPTransaction *tx = (SMTPTransaction *)txv;
const uint8_t *b_email_received = NULL;
uint32_t b_email_received_len = 0;
if (tx->mime_state == NULL) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
if (SCDetectMimeEmailGetDataArray(
tx->mime_state, &b_email_received, &b_email_received_len, "received", idx) != 1) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(det_ctx, buffer, transforms, b_email_received, b_email_received_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
return buffer;
}
void DetectEmailRegister(void)
{
SCSigTableElmt kw = { 0 };
@ -405,4 +446,15 @@ void DetectEmailRegister(void)
DetectHelperMultiBufferMpmRegister("email.url", "MIME EMAIL URL", ALPROTO_SMTP, false,
true, // to server
GetMimeEmailUrlData);
kw.name = "email.received";
kw.desc = "'Received' field from an email";
kw.url = "/rules/email-keywords.html#email.received";
kw.Setup = (int (*)(void *, void *, const char *))DetectMimeEmailReceivedSetup;
kw.flags = SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
DetectHelperKeywordRegister(&kw);
g_mime_email_received_buffer_id = DetectHelperMultiBufferMpmRegister("email.received",
"MIME EMAIL RECEIVED", ALPROTO_SMTP, false,
true, // to server
GetMimeEmailReceivedData);
}

Loading…
Cancel
Save