detect: log app-layer metadata in alert with single tx

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.

(cherry picked from commit f2c3776314)
pull/12270/head
Philippe Antoine 12 months ago committed by Victor Julien
parent c84599a59e
commit 19a638611b

@ -62,6 +62,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:

@ -59,6 +59,10 @@ Upgrading to 7.0.8
7.0 releases. It will not be provided in
Suricata 8. Please fix any rules that depend on this
behavior.
- 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
--------------------

@ -112,6 +112,10 @@
"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,

@ -281,6 +281,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

@ -2922,7 +2922,14 @@ static int DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx)
SCLogDebug("de_ctx->inspection_recursion_limit: %d",
de_ctx->inspection_recursion_limit);
/* parse port grouping whitelisting settings */
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 */
const char *ports = NULL;
(void)ConfGet("detect.grouping.tcp-whitelist", &ports);

@ -818,16 +818,19 @@ 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;
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
alert_flags |= PACKET_ALERT_FLAG_TX;
if (pflow->proto != IPPROTO_UDP) {
alert_flags |= PACKET_ALERT_FLAG_TX_GUESSED;
}
}
}
AlertQueueAppend(det_ctx, s, p, txid, alert_flags);

@ -885,6 +885,9 @@ typedef struct DetectEngineCtx_ {
/* maximum recursion depth for content inspection */
int inspection_recursion_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;

@ -378,6 +378,9 @@ void AlertJsonHeader(void *ctx, const Packet *p, const PacketAlert *pa, JsonBuil
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");

@ -1677,6 +1677,11 @@ detect:
toserver-groups: 25
sgh-mpm-context: auto
inspection-recursion-limit: 3000
# 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

Loading…
Cancel
Save