diff --git a/doc/userguide/rules/email-keywords.rst b/doc/userguide/rules/email-keywords.rst index 0971f53e47..c5e76840b8 100644 --- a/doc/userguide/rules/email-keywords.rst +++ b/doc/userguide/rules/email-keywords.rst @@ -74,3 +74,27 @@ Example of a signature that would alert if a packet contains the MIME field ``to .. container:: example-rule alert smtp any any -> any any (msg:"Test mime email to"; :example-rule-emphasis:`email.to; content:"172.16.92.2@linuxbox";` sid:1;) + +email.cc +-------- + +Matches the MIME ``Cc`` field of an email. + +Comparison is case-sensitive. + +Syntax:: + + email.cc; content:""; + +``email.cc`` is a 'sticky buffer' and can be used as a ``fast_pattern``. + +This keyword maps to the EVE field ``email.cc[]`` + +Example +^^^^^^^ + +Example of a signature that would alert if a packet contains the MIME field ``cc`` with the value ``Emily , Ava , Sophia Wilson `` + +.. container:: example-rule + + alert smtp any any -> any any (msg:"Test mime email cc"; :example-rule-emphasis:`email.cc; content:"Emily , Ava , Sophia Wilson ";` sid:1;) diff --git a/doc/userguide/rules/multi-buffer-matching.rst b/doc/userguide/rules/multi-buffer-matching.rst index e9d4c0f8e1..1985f389a9 100644 --- a/doc/userguide/rules/multi-buffer-matching.rst +++ b/doc/userguide/rules/multi-buffer-matching.rst @@ -47,7 +47,7 @@ Example rule: The above rule will alert on a single dns query containing "example.net" or "example.domain.net" since the rule content -matches are within a single ``dns.query`` buffer and all +matches are within a single ``dns.query`` buffer and all content match requirements of the rule are met. @@ -65,7 +65,7 @@ Using our example from above, the first query is for example.net which matches content:"example"; but does not match content:".com"; The second query is for something.com which would match on the -content:".com"; but not the content:"example"; +content:".com"; but not the content:"example"; So with the Suricata behavior prior to Suricata 7, the signature would not fire in this case since both content conditions will diff --git a/rust/src/mime/detect.rs b/rust/src/mime/detect.rs index 802b0811a1..57d8f10214 100644 --- a/rust/src/mime/detect.rs +++ b/rust/src/mime/detect.rs @@ -20,6 +20,8 @@ use super::smtp::MimeStateSMTP; use std::ffi::CStr; use std::ptr; +/// Intermediary function used in detect-email.c to access data from the MimeStateSMTP structure. +/// The hname parameter determines which data will be returned. #[no_mangle] pub unsafe extern "C" fn SCDetectMimeEmailGetData( ctx: &MimeStateSMTP, buffer: *mut *const u8, buffer_len: *mut u32, diff --git a/src/detect-email.c b/src/detect-email.c index a88122e92d..543689c005 100644 --- a/src/detect-email.c +++ b/src/detect-email.c @@ -25,6 +25,7 @@ static int g_mime_email_from_buffer_id = 0; static int g_mime_email_subject_buffer_id = 0; static int g_mime_email_to_buffer_id = 0; +static int g_mime_email_cc_buffer_id = 0; static int DetectMimeEmailFromSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) { @@ -131,6 +132,40 @@ static InspectionBuffer *GetMimeEmailToData(DetectEngineThreadCtx *det_ctx, return buffer; } +static int DetectMimeEmailCcSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) +{ + if (DetectBufferSetActiveList(de_ctx, s, g_mime_email_cc_buffer_id) < 0) + return -1; + + if (DetectSignatureSetAppProto(s, ALPROTO_SMTP) < 0) + return -1; + + return 0; +} + +static InspectionBuffer *GetMimeEmailCcData(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, Flow *f, const uint8_t _flow_flags, void *txv, + const int list_id) +{ + InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); + if (buffer->inspect == NULL) { + SMTPTransaction *tx = (SMTPTransaction *)txv; + + const uint8_t *b_email_cc = NULL; + uint32_t b_email_cc_len = 0; + + if (tx->mime_state == NULL) + return NULL; + + if (SCDetectMimeEmailGetData(tx->mime_state, &b_email_cc, &b_email_cc_len, "cc") != 1) + return NULL; + + InspectionBufferSetup(det_ctx, list_id, buffer, b_email_cc, b_email_cc_len); + InspectionBufferApplyTransforms(buffer, transforms); + } + return buffer; +} + void DetectEmailRegister(void) { SCSigTableElmt kw = { 0 }; @@ -167,4 +202,15 @@ void DetectEmailRegister(void) DetectHelperBufferMpmRegister("email.to", "MIME EMAIL TO", ALPROTO_SMTP, false, true, // to server GetMimeEmailToData); + + kw.name = "email.cc"; + kw.desc = "'Cc' field from an email"; + kw.url = "/rules/email-keywords.html#email.cc"; + kw.Setup = (int (*)(void *, void *, const char *))DetectMimeEmailCcSetup; + kw.flags = SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; + DetectHelperKeywordRegister(&kw); + g_mime_email_cc_buffer_id = + DetectHelperBufferMpmRegister("email.cc", "MIME EMAIL CC", ALPROTO_SMTP, false, + true, // to server + GetMimeEmailCcData); }