]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: safety for app-layer logging of stream-only rules
authorPhilippe Antoine <pantoine@oisf.net>
Fri, 31 May 2024 12:06:55 +0000 (14:06 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 20 Sep 2024 09:49:14 +0000 (11:49 +0200)
If a stream-only rule matches, and we find a tx where we
want to log the app-layer data, store into the tx data that
we already logged, so that we do not log again the app-layer metadata

Ticket: 7085

doc/userguide/configuration/suricata-yaml.rst
rust/src/applayer.rs
src/detect-engine.c
src/detect.c
src/detect.h
suricata.yaml.in

index b348a49fc2a7b91065775710e4a552433b4dfb57..ce7cd76a852cb1b1b6645df2c9628e4745cee10b 100644 (file)
@@ -659,6 +659,7 @@ The detection-engine builds internal groups of signatures. Suricata loads signat
       toserver-groups: 25
     sgh-mpm-context: auto
     inspection-recursion-limit: 3000
+    stream-tx-log-limit: 4
 
 At all of these options, you can add (or change) a value. Most
 signatures have the adjustment to focus on one direction, meaning
@@ -693,6 +694,11 @@ complicated issues. It could end up in an 'endless loop' due to a bug,
 meaning it will repeat its actions over and over again. With the
 option inspection-recursion-limit you can limit this action.
 
+The stream-tx-log-limit defines the maximum number of times a
+transaction will get logged for a stream-only rule match.
+This is meant to avoid logging the same data an arbitrary number
+of times.
+
 *Example 4     Detection-engine grouping tree*
 
 .. image:: suricata-yaml/grouping_tree.png
index 92bab1d82fb0e97debacc1567ace8ff7cda1f3c3..f863546bbe0606a769d3d70ffa16fa1b3abc5191 100644 (file)
@@ -114,6 +114,8 @@ pub struct AppLayerTxData {
     /// STREAM_TOCLIENT: file tx , files only in toclient dir
     /// STREAM_TOSERVER|STREAM_TOCLIENT: files possible in both dirs
     pub file_tx: u8,
+    /// Number of times this tx data has already been logged for one stream match
+    pub stream_logged: u8,
 
     /// detection engine flags for use by detection engine
     detect_flags_ts: u64,
@@ -152,6 +154,7 @@ impl AppLayerTxData {
             files_stored: 0,
             file_flags: 0,
             file_tx: 0,
+            stream_logged: 0,
             detect_flags_ts: 0,
             detect_flags_tc: 0,
             de_state: std::ptr::null_mut(),
@@ -174,6 +177,7 @@ impl AppLayerTxData {
             files_stored: 0,
             file_flags: 0,
             file_tx: 0,
+            stream_logged: 0,
             detect_flags_ts,
             detect_flags_tc,
             de_state: std::ptr::null_mut(),
index c4e79682f1afdb264f5ab3b17c3f3e4996f0a33f..58b5c9967c8bbef2695decd077630d819b0e57ac 100644 (file)
@@ -2904,6 +2904,17 @@ static int DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx)
     SCLogDebug("de_ctx->inspection_recursion_limit: %d",
                de_ctx->inspection_recursion_limit);
 
+    // default value is 4
+    de_ctx->stream_tx_log_limit = 4;
+    if (ConfGetInt("detect.stream-tx-log-limit", &value) == 1) {
+        if (value >= 0 && value <= UINT8_MAX) {
+            de_ctx->stream_tx_log_limit = (uint8_t)value;
+        } else {
+            SCLogWarning("Invalid value for detect-engine.stream-tx-log-limit: must be between 0 "
+                         "and 255, will default to 4");
+        }
+    }
+
     /* parse port grouping whitelisting settings */
 
     const char *ports = NULL;
index 70612516fbd3ed661922a0e90fbe5e198a8da8d4..03fa8437068d88771b0d1c59520d346a1071f104 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "suricata-common.h"
 #include "suricata.h"
-#include "conf.h"
 
 #include "decode.h"
 #include "packet.h"
@@ -823,7 +822,15 @@ static inline void DetectRulePacketRules(
                 uint8_t dir =
                         (p->flowflags & FLOW_PKT_TOCLIENT) ? STREAM_TOCLIENT : STREAM_TOSERVER;
                 txid = AppLayerParserGetTransactionInspectId(pflow->alparser, dir);
-                alert_flags |= PACKET_ALERT_FLAG_TX;
+                void *tx_ptr =
+                        AppLayerParserGetTx(pflow->proto, pflow->alproto, pflow->alstate, txid);
+                AppLayerTxData *txd =
+                        tx_ptr ? AppLayerParserGetTxData(pflow->proto, pflow->alproto, tx_ptr)
+                               : NULL;
+                if (txd && txd->stream_logged < de_ctx->stream_tx_log_limit) {
+                    alert_flags |= PACKET_ALERT_FLAG_TX;
+                    txd->stream_logged++;
+                }
             }
         }
         AlertQueueAppend(det_ctx, s, p, txid, alert_flags);
index 4df2dfa3d623b96f0b06f2080d5324f772208c98..cf8f4335b19722ddaeac120469c5efd678fb3166 100644 (file)
@@ -884,6 +884,9 @@ typedef struct DetectEngineCtx_ {
     /* maximum recursion depth for content inspection */
     int inspection_recursion_limit;
 
+    /* maximum number of times a tx will get logged for a stream-only rule match */
+    uint8_t stream_tx_log_limit;
+
     /* registration id for per thread ctx for the filemagic/file.magic keywords */
     int filemagic_thread_ctx_id;
 
index 2e5f722c366c0ecca8b1af3fd1b22061e07080f6..3e73623c4b21388658e8ddc2ddf17bdc2cd760e5 100644 (file)
@@ -1686,6 +1686,8 @@ detect:
     toserver-groups: 25
   sgh-mpm-context: auto
   inspection-recursion-limit: 3000
+  # maximum number of times a tx will get logged for a stream-only rule match
+  # stream-tx-log-limit: 4
   # If set to yes, the loading of signatures will be made after the capture
   # is started. This will limit the downtime in IPS mode.
   #delayed-detect: yes