]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: log app-layer metadata in alert with single tx
authorPhilippe Antoine <pantoine@oisf.net>
Tue, 26 Nov 2024 20:44:45 +0000 (21:44 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 10 Dec 2024 13:40:07 +0000 (14:40 +0100)
Ticket: 7199

Uses a config parameter detect.guess-applayer-tx to enable
this behavior (off by default)

This feature is requested for use cases with signatures not
using app-layer keywords but still targetting application
layer transactions, such as pass/drop rule combination,
or lua usage.

This overrides the previous behavior of checking if the signature
has a content match, by checking if there is only one live
transaction, in addition to the config parameter being set.

doc/userguide/output/eve/eve-json-output.rst
doc/userguide/upgrade.rst
etc/schema.json
src/decode.h
src/detect-engine.c
src/detect.c
src/detect.h
src/output-json-alert.c
suricata.yaml.in

index 269024e5eb746836726d27daf3833bd15d1f7769..da80a3fd196bf1b140896e5d42f4395309f7746e 100644 (file)
@@ -70,6 +70,21 @@ Alerts are event records for rule matches. They can be amended with
 metadata, such as the application layer record (HTTP, DNS, etc) an
 alert was generated for, and elements of the rule.
 
+The alert is amended with application layer metadata for signatures
+using application layer keywords. It is also the case for protocols
+over UDP as each single packet is expected to contain a PDU.
+
+For other signatures, the option ``guess-applayer-tx``
+can be used to force the detect engine to tie a transaction
+to an alert.
+This transaction is not guaranteed to be the relevant one,
+depending on your use case and how you define relevant here.
+If there are multiple live transactions, none will get
+picked up.
+The alert event will have ``"tx_guessed": true`` to recognize
+these alerts.
+
+
 Metadata::
 
         - alert:
index 7172c6b1c8b1dc5531276aeaf13f50a2aea28d9e..2b16dd31a35cad648d3260b92a5a19e32524fe05 100644 (file)
@@ -99,6 +99,10 @@ Logging changes
 ~~~~~~~~~~~~~~~
 - RFB security result is now consistently logged as ``security_result`` when it was
   sometimes logged with a dash instead of an underscore.
+- Application layer metadata is logged with alerts by default **only for rules that
+  use application layer keywords**. For other rules, the configuration parameter
+  ``detect.guess-applayer-tx`` can be used to force the detect engine to find a
+  transaction, which is not guaranteed to be the one you expect.
 
 Upgrading 6.0 to 7.0
 --------------------
index e27ffb559b8d40d081f072892b13e6c154c05654..b335dc5c210428471c03118b5f5fe6d1ea9b590d 100644 (file)
         "tx_id": {
             "type": "integer"
         },
+        "tx_guessed": {
+            "description": "the signature that triggered this alert didn't tie to a transaction, so the transaction (and metadata) logged is a forced estimation and may not be the one you expect",
+            "type": "boolean"
+        },
         "files": {
             "type": "array",
             "minItems": 1,
index f36c41a8422e18b622ba4f3fd7f96b09ace26085..f7ef222336260c24d33ff25faf356d987db420b6 100644 (file)
@@ -257,6 +257,8 @@ typedef struct PacketAlert_ {
 #define PACKET_ALERT_RATE_FILTER_MODIFIED   0x10
 /** alert is in a frame, frame_id set */
 #define PACKET_ALERT_FLAG_FRAME 0x20
+/** alert in a tx was forced */
+#define PACKET_ALERT_FLAG_TX_GUESSED 0x040
 
 extern uint16_t packet_alert_max;
 #define PACKET_ALERT_MAX 15
index f4195739e2c11897199cb491d6cf58d027901b1e..f923ab81f6b0a168266ec54095b3ce6873d70b8b 100644 (file)
@@ -2940,6 +2940,12 @@ static int DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx)
                          "and 255, will default to 4");
         }
     }
+    int guess_applayer = 0;
+    if ((ConfGetBool("detect.guess-applayer-tx", &guess_applayer)) == 1) {
+        if (guess_applayer == 1) {
+            de_ctx->guess_applayer = true;
+        }
+    }
 
     /* parse port grouping priority settings */
 
index 802cf690ce22c5a6bb51716b1f48d692bae3395e..66770500e233d0e689bad1186ac962ffb5fadd35 100644 (file)
@@ -813,15 +813,15 @@ static inline void DetectRulePacketRules(
         DetectRunPostMatch(tv, det_ctx, p, s);
 
         uint64_t txid = PACKET_ALERT_NOTX;
-        if ((alert_flags & PACKET_ALERT_FLAG_STREAM_MATCH) ||
-                (s->alproto != ALPROTO_UNKNOWN && pflow->proto == IPPROTO_UDP)) {
-            // if there is a stream match (TCP), or
-            // a UDP specific app-layer signature,
-            // try to use the good tx for the packet direction
-            if (pflow->alstate) {
-                uint8_t dir =
-                        (p->flowflags & FLOW_PKT_TOCLIENT) ? STREAM_TOCLIENT : STREAM_TOSERVER;
-                txid = AppLayerParserGetTransactionInspectId(pflow->alparser, dir);
+        if (pflow && pflow->alstate) {
+            uint8_t dir = (p->flowflags & FLOW_PKT_TOCLIENT) ? STREAM_TOCLIENT : STREAM_TOSERVER;
+            txid = AppLayerParserGetTransactionInspectId(pflow->alparser, dir);
+            if ((s->alproto != ALPROTO_UNKNOWN && pflow->proto == IPPROTO_UDP) ||
+                    (de_ctx->guess_applayer &&
+                            AppLayerParserGetTxCnt(pflow, pflow->alstate) == txid + 1)) {
+                // if there is a UDP specific app-layer signature,
+                // or only one live transaction
+                // try to use the good tx for the packet direction
                 void *tx_ptr =
                         AppLayerParserGetTx(pflow->proto, pflow->alproto, pflow->alstate, txid);
                 AppLayerTxData *txd =
@@ -829,6 +829,9 @@ static inline void DetectRulePacketRules(
                                : NULL;
                 if (txd && txd->stream_logged < de_ctx->stream_tx_log_limit) {
                     alert_flags |= PACKET_ALERT_FLAG_TX;
+                    if (pflow->proto != IPPROTO_UDP) {
+                        alert_flags |= PACKET_ALERT_FLAG_TX_GUESSED;
+                    }
                     txd->stream_logged++;
                 }
             }
index e88b5540ac797df98dc91983d75d1aadb0a03eb4..c8bdafdcaa8a1f70610a89019e8c9f04d1a5375c 100644 (file)
@@ -889,6 +889,9 @@ typedef struct DetectEngineCtx_ {
     /* maximum number of times a tx will get logged for a stream-only rule match */
     uint8_t stream_tx_log_limit;
 
+    /* force app-layer tx finding for alerts with signatures not having app-layer keywords */
+    bool guess_applayer;
+
     /* registration id for per thread ctx for the filemagic/file.magic keywords */
     int filemagic_thread_ctx_id;
 
index 48672b98516d7afce44f916b8a8dfa3984d44c3d..c5c15d32b5a58cb1d55d7badd74fc0d8e012aa68 100644 (file)
@@ -221,6 +221,9 @@ void AlertJsonHeader(const Packet *p, const PacketAlert *pa, JsonBuilder *js, ui
     if (pa->flags & PACKET_ALERT_FLAG_TX) {
         jb_set_uint(js, "tx_id", pa->tx_id);
     }
+    if (pa->flags & PACKET_ALERT_FLAG_TX_GUESSED) {
+        jb_set_bool(js, "tx_guessed", true);
+    }
 
     jb_open_object(js, "alert");
 
index 82a72bad0f3a52f2521e83b3bf5f817e7cbd9d20..0a1ae54cc4b9abec5332f2b94b7bc79400967e86 100644 (file)
@@ -1702,6 +1702,11 @@ detect:
   inspection-recursion-limit: 3000
   # maximum number of times a tx will get logged for a stream-only rule match
   # stream-tx-log-limit: 4
+  # try to tie an app-layer transaction for rules without app-layer keywords
+  # if there is only one live transaction for the flow
+  # allows to log app-layer metadata in alert
+  # but the transaction may not be the relevant one.
+  # guess-applayer-tx: no
   # 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