From e5d50ce1e1316a4bdc73810c9d85f1e90c42428d Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 26 Nov 2024 21:44:45 +0100 Subject: [PATCH] detect: log app-layer metadata in alert with single tx Ticket: 7199 Uses a config parameter detect.force-applayer-findtx 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 | 15 ++++++++++++++ doc/userguide/upgrade.rst | 4 ++++ etc/schema.json | 4 ++++ src/decode.h | 2 ++ src/detect-engine.c | 6 ++++++ src/detect.c | 21 +++++++++++--------- src/detect.h | 3 +++ src/output-json-alert.c | 3 +++ suricata.yaml.in | 4 ++++ 9 files changed, 53 insertions(+), 9 deletions(-) diff --git a/doc/userguide/output/eve/eve-json-output.rst b/doc/userguide/output/eve/eve-json-output.rst index 269024e5eb74..7f1ff87006a7 100644 --- a/doc/userguide/output/eve/eve-json-output.rst +++ b/doc/userguide/output/eve/eve-json-output.rst @@ -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 ``detect.force-applayer-findtx`` +can be used to force the detect engine to find a transaction. +These signatures need to define an app-layer protocol. +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_id_forced": true`` to recognize +these alerts. + + Metadata:: - alert: diff --git a/doc/userguide/upgrade.rst b/doc/userguide/upgrade.rst index 63e2146280ab..4cde244aa39c 100644 --- a/doc/userguide/upgrade.rst +++ b/doc/userguide/upgrade.rst @@ -96,6 +96,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.force-applayer-findtx`` 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 -------------------- diff --git a/etc/schema.json b/etc/schema.json index 08959e3c7a1d..c236e0d20bc1 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -115,6 +115,10 @@ "tx_id": { "type": "integer" }, + "tx_id_forced": { + "description": "the transaction for this alert event was forced, so the transaction may not be the one you expect", + "type": "boolean" + }, "files": { "type": "array", "minItems": 1, diff --git a/src/decode.h b/src/decode.h index f36c41a8422e..3dfc3938a859 100644 --- a/src/decode.h +++ b/src/decode.h @@ -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_FORCED 0x040 extern uint16_t packet_alert_max; #define PACKET_ALERT_MAX 15 diff --git a/src/detect-engine.c b/src/detect-engine.c index 77c25a1cf3a9..d3c7397b867b 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -2928,6 +2928,12 @@ static int DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx) "and 255, will default to 4"); } } + int force_applayer = 0; + if ((ConfGetBool("detect.force-applayer-findtx", &force_applayer)) == 1) { + if (force_applayer == 1) { + de_ctx->force_applayer = true; + } + } /* parse port grouping priority settings */ diff --git a/src/detect.c b/src/detect.c index 03fa8437068d..fc22b5fa6b22 100644 --- a/src/detect.c +++ b/src/detect.c @@ -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->force_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_FORCED; + } txd->stream_logged++; } } diff --git a/src/detect.h b/src/detect.h index fe755b7f0d14..b74211e33e14 100644 --- a/src/detect.h +++ b/src/detect.h @@ -887,6 +887,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 */ + uint8_t force_applayer; + /* registration id for per thread ctx for the filemagic/file.magic keywords */ int filemagic_thread_ctx_id; diff --git a/src/output-json-alert.c b/src/output-json-alert.c index 91a55828a7a1..c60a8addc28a 100644 --- a/src/output-json-alert.c +++ b/src/output-json-alert.c @@ -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_FORCED) { + jb_set_bool(js, "tx_id_forced", true); + } jb_open_object(js, "alert"); diff --git a/suricata.yaml.in b/suricata.yaml.in index 82a72bad0f3a..376bb5dced40 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -1702,6 +1702,10 @@ 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 find an app-layer transaction for rules without app-layer keywords + # allows to log app-layer metadata in alert + # but the transaction may not be the relevant one. + # force-applayer-findtx: 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