From 90aab0d62fe74cd299af6d0182941798e863bb4e Mon Sep 17 00:00:00 2001 From: Alice Akaki Date: Fri, 14 Mar 2025 22:32:54 -0400 Subject: [PATCH] detect: add email.from email.from matches on MIME EMAIL FROM This keyword maps to the EVE field email.from It is a sticky buffer Supports prefiltering Ticket: #7592 --- doc/userguide/rules/email-keywords.rst | 28 +++++++++ doc/userguide/rules/index.rst | 1 + rust/src/mime/detect.rs | 43 ++++++++++++++ rust/src/mime/mod.rs | 1 + src/Makefile.am | 2 + src/detect-email.c | 78 ++++++++++++++++++++++++++ src/detect-email.h | 23 ++++++++ src/detect-engine-register.c | 3 + 8 files changed, 179 insertions(+) create mode 100644 doc/userguide/rules/email-keywords.rst create mode 100644 rust/src/mime/detect.rs create mode 100644 src/detect-email.c create mode 100644 src/detect-email.h diff --git a/doc/userguide/rules/email-keywords.rst b/doc/userguide/rules/email-keywords.rst new file mode 100644 index 0000000000..b7924b250a --- /dev/null +++ b/doc/userguide/rules/email-keywords.rst @@ -0,0 +1,28 @@ +Email Keywords +============== + +.. role:: example-rule-emphasis + +email.from +---------- + +Matches the MIME ``From`` field of an email. + +Comparison is case-sensitive. + +Syntax:: + + email.from; content:""; + +``email.from`` is a 'sticky buffer' and can be used as a ``fast_pattern``. + +This keyword maps to the EVE field ``email.from`` + +Example +^^^^^^^ + +Example of a signature that would alert if a packet contains the MIME field ``from`` with the value ``toto `` + +.. container:: example-rule + + alert smtp any any -> any any (msg:"Test mime email from"; :example-rule-emphasis:`email.from; content:"toto ";` sid:1;) diff --git a/doc/userguide/rules/index.rst b/doc/userguide/rules/index.rst index b475fba0f8..70b8013116 100644 --- a/doc/userguide/rules/index.rst +++ b/doc/userguide/rules/index.rst @@ -53,3 +53,4 @@ Suricata Rules vlan-keywords ldap-keywords rule-types + email-keywords diff --git a/rust/src/mime/detect.rs b/rust/src/mime/detect.rs new file mode 100644 index 0000000000..802b0811a1 --- /dev/null +++ b/rust/src/mime/detect.rs @@ -0,0 +1,43 @@ +/* Copyright (C) 2025 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use super::mime; +use super::smtp::MimeStateSMTP; +use std::ffi::CStr; +use std::ptr; + +#[no_mangle] +pub unsafe extern "C" fn SCDetectMimeEmailGetData( + ctx: &MimeStateSMTP, buffer: *mut *const u8, buffer_len: *mut u32, + hname: *const std::os::raw::c_char, +) -> u8 { + let c_str = CStr::from_ptr(hname); //unsafe + let str = c_str.to_str().unwrap_or(""); + + for h in &ctx.headers[..ctx.main_headers_nb] { + if mime::slice_equals_lowercase(&h.name, str.as_bytes()) { + *buffer = h.value.as_ptr(); + *buffer_len = h.value.len() as u32; + return 1; + } + } + + *buffer = ptr::null(); + *buffer_len = 0; + + return 0; +} diff --git a/rust/src/mime/mod.rs b/rust/src/mime/mod.rs index 2eac4d1bd4..a126b79d4a 100644 --- a/rust/src/mime/mod.rs +++ b/rust/src/mime/mod.rs @@ -17,6 +17,7 @@ //! MIME protocol parser module. +pub mod detect; pub mod mime; pub mod smtp; pub mod smtp_log; diff --git a/src/Makefile.am b/src/Makefile.am index 4ebd1a6407..8fd7e20172 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -317,6 +317,7 @@ noinst_HEADERS = \ detect-within.h \ detect-xbits.h \ detect-vlan.h \ + detect-email.h \ device-storage.h \ feature.h \ flow-bit.h \ @@ -891,6 +892,7 @@ libsuricata_c_a_SOURCES = \ detect-within.c \ detect-xbits.c \ detect-vlan.c \ + detect-email.c \ device-storage.c \ feature.c \ flow-bit.c \ diff --git a/src/detect-email.c b/src/detect-email.c new file mode 100644 index 0000000000..23a69d66b6 --- /dev/null +++ b/src/detect-email.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2025 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "detect-engine.h" +#include "detect-engine-helper.h" +#include "detect-parse.h" +#include "app-layer-smtp.h" +#include "detect-email.h" +#include "rust.h" + +static int g_mime_email_from_buffer_id = 0; + +static int DetectMimeEmailFromSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) +{ + if (DetectBufferSetActiveList(de_ctx, s, g_mime_email_from_buffer_id) < 0) + return -1; + + if (DetectSignatureSetAppProto(s, ALPROTO_SMTP) < 0) + return -1; + + return 0; +} + +static InspectionBuffer *GetMimeEmailFromData(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_from = NULL; + uint32_t b_email_from_len = 0; + + if ((tx->mime_state != NULL)) { + if (SCDetectMimeEmailGetData( + tx->mime_state, &b_email_from, &b_email_from_len, "from") != 1) + return NULL; + } + + if (b_email_from == NULL || b_email_from_len == 0) + return NULL; + + InspectionBufferSetup(det_ctx, list_id, buffer, b_email_from, b_email_from_len); + InspectionBufferApplyTransforms(buffer, transforms); + } + return buffer; +} + +void DetectEmailRegister(void) +{ + SCSigTableElmt kw = { 0 }; + + kw.name = "email.from"; + kw.desc = "'From' field from an email"; + kw.url = "/rules/email-keywords.html#email.from"; + kw.Setup = (int (*)(void *, void *, const char *))DetectMimeEmailFromSetup; + kw.flags = SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; + DetectHelperKeywordRegister(&kw); + g_mime_email_from_buffer_id = + DetectHelperBufferMpmRegister("email.from", "MIME EMAIL FROM", ALPROTO_SMTP, false, + true, // to server + GetMimeEmailFromData); +} diff --git a/src/detect-email.h b/src/detect-email.h new file mode 100644 index 0000000000..107c6d1772 --- /dev/null +++ b/src/detect-email.h @@ -0,0 +1,23 @@ +/* Copyright (C) 2025 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef SURICATA_DETECT_EMAIL_H +#define SURICATA_DETECT_EMAIL_H + +void DetectEmailRegister(void); + +#endif /* SURICATA_DETECT_EMAIL_H */ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 10af70b1d0..8aa70757d6 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -252,6 +252,7 @@ #include "detect-ike-nonce-payload.h" #include "detect-ike-key-exchange-payload.h" #include "detect-vlan.h" +#include "detect-email.h" #include "action-globals.h" #include "tm-threads.h" @@ -733,6 +734,8 @@ void SigTableSetup(void) DetectVlanIdRegister(); DetectVlanLayersRegister(); + DetectEmailRegister(); + SCDetectSMTPRegister(); SCDetectSNMPRegister(); SCDetectDHCPRegister();