From 34bad52cefd7fa9744a948df0bccafb253a1535c Mon Sep 17 00:00:00 2001 From: Juliana Fajardini Date: Thu, 15 Dec 2022 14:59:20 -0300 Subject: [PATCH] output/eve: add verdict field w final packet action The eve logs have a field alert.action that will say something like 'allowed' even if a packet gets blocked by some other rule. To make this less ambiguous, added a field to the alert and drop events indicating the final verdict by the engine for a given packet. Bug #5464 --- doc/userguide/output/eve/eve-json-format.rst | 20 ++++++++++++++++++-- etc/schema.json | 3 +++ src/decode.c | 18 ++++++++++++++++++ src/decode.h | 1 + src/output-json-alert.c | 8 ++++++-- src/output-json-drop.c | 3 +++ src/output-json.c | 3 +++ 7 files changed, 52 insertions(+), 4 deletions(-) diff --git a/doc/userguide/output/eve/eve-json-format.rst b/doc/userguide/output/eve/eve-json-format.rst index 6934d6aa7ebf..676cb0619211 100644 --- a/doc/userguide/output/eve/eve-json-format.rst +++ b/doc/userguide/output/eve/eve-json-format.rst @@ -92,7 +92,7 @@ Event type: Alert Field action ~~~~~~~~~~~~ -Possible values: "allowed" and "blocked" +Possible values: "allowed" and "blocked". Example: @@ -101,7 +101,7 @@ Example: "action":"allowed" -Action is set to "allowed" unless a rule used the "drop" action and Suricata is in IPS mode, or when the rule used the "reject" action. +Action is set to "allowed" unless a rule used the "drop" action and Suricata is in IPS mode, or when the rule used the "reject" action. It is important to note that this does not necessarily indicate the final verdict for a given packet or flow, since one packet may match on several rules. It can also contain information about Source and Target of the attack in the alert.source and alert.target field if target keyword is used in the signature. @@ -147,6 +147,22 @@ the signature. } }, +Verdict Field +~~~~~~~~~~~~~ + +Possible values are "accept", "drop" or "reject". + +Example: + +:: + + + "verdict":"drop" + +Verdict is the final action that will be applied to a given packet, based on all +the signatures triggered by it. In IPS mode, all values are possible. In IDS +mode, verdict is only present if its value is "reject". + Pcap Field ~~~~~~~~~~ diff --git a/etc/schema.json b/etc/schema.json index 962161d301e8..e1d42a65516c 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -100,6 +100,9 @@ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d+[+\\-]\\d+$", "optional": false }, + "verdict": { + "type": "string" + }, "direction": { "type": "string", "optional": true diff --git a/src/decode.c b/src/decode.c index 96c618cf2c25..1c05e3718a34 100644 --- a/src/decode.c +++ b/src/decode.c @@ -819,6 +819,24 @@ const char *PacketDropReasonToString(enum PacketDropReason r) return NULL; } +/** \brief Decide Packet's final verdict based on packet action, return it as a string */ +const char *PacketActionVerdictToString(const Packet *p) +{ + /* Reject is valid in both IDS and IPS */ + if (PacketCheckAction(p, ACTION_REJECT_ANY)) { + return "reject"; + } else if (EngineModeIsIPS()) { + /* Verdicts will be reject, drop, or accept */ + if (PacketCheckAction(p, ACTION_DROP)) { + return "drop"; + } + return "accept"; + } + + /* If we're in IDS mode and action isn't reject, we won't log verdict */ + return NULL; +} + /* TODO drop reason stats! */ void CaptureStatsUpdate(ThreadVars *tv, CaptureStats *s, const Packet *p) { diff --git a/src/decode.h b/src/decode.h index ecc8c88f8326..f828493d69a5 100644 --- a/src/decode.h +++ b/src/decode.h @@ -838,6 +838,7 @@ void DecodeThreadVarsFree(ThreadVars *, DecodeThreadVars *); void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p); const char *PacketDropReasonToString(enum PacketDropReason r); +const char *PacketActionVerdictToString(const Packet *p); /* decoder functions */ int DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t); diff --git a/src/output-json-alert.c b/src/output-json-alert.c index ff0c14046a30..069512f92179 100644 --- a/src/output-json-alert.c +++ b/src/output-json-alert.c @@ -826,12 +826,16 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) jb_set_string(jb, "capture_file", pcap_filename); } + if (PacketActionVerdictToString(p) != NULL) { + const char *verdict = PacketActionVerdictToString(p); + jb_set_string(jb, "verdict", verdict); + } + OutputJsonBuilderBuffer(jb, aft->ctx); jb_free(jb); } - if ((p->flags & PKT_HAS_TAG) && (json_output_ctx->flags & - LOG_JSON_TAGGED_PACKETS)) { + if ((p->flags & PKT_HAS_TAG) && (json_output_ctx->flags & LOG_JSON_TAGGED_PACKETS)) { JsonBuilder *packetjs = CreateEveHeader(p, LOG_DIR_PACKET, "packet", NULL, json_output_ctx->eve_ctx); if (unlikely(packetjs != NULL)) { diff --git a/src/output-json-drop.c b/src/output-json-drop.c index 39d283d3aadd..4fa6704addd4 100644 --- a/src/output-json-drop.c +++ b/src/output-json-drop.c @@ -158,6 +158,9 @@ static int DropLogJSON (JsonDropLogThread *aft, const Packet *p) /* Close drop. */ jb_close(js); + const char *verdict = PacketActionVerdictToString(p); + jb_set_string(js, "verdict", verdict); + if (aft->drop_ctx->flags & LOG_DROP_ALERTS) { int logged = 0; int i; diff --git a/src/output-json.c b/src/output-json.c index 9fe8b5c8b7c8..b6041a1944c6 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -52,6 +52,9 @@ #include "output.h" #include "output-json.h" +#include "packet.h" +#include "action-globals.h" + #include "util-byte.h" #include "util-privs.h" #include "util-print.h"