detect: log the hook for sub-state firewall rules

Alerts and drops for firewall rules hooked at a sub-state (http2
stream/global) had no firewall.hook field: the logger resolved the state
name without the sub-state, so the lookup found nothing.

Keep the rule's sub-state on the Signature next to app_progress_hook,
set it from the hook and for the default policy signatures, resolve the
name in the sub-state table, and fall back to the plain state name when
that lookup fails.

Ticket: #8944.
pull/16368/head
Victor Julien 1 month ago
parent 9419f15779
commit 2630c6a5d3

@ -122,6 +122,11 @@ alert
action in firewall rules. The effect will be the creation of an alert event when the action in firewall rules. The effect will be the creation of an alert event when the
firewall rule matches. firewall rule matches.
For application layer transactions the alert event carries a ``firewall`` object with
the resolved ``policy`` and, when the protocol registers a state name callback, the
``hook`` the rule was registered at. Protocols without such a callback (``quic``,
``modbus``, ``rdp``) omit the ``hook`` key; the policy is still reported.
config config
~~~~~~ ~~~~~~

@ -1575,6 +1575,8 @@ static int SigParseProtoHookApp(
s->init_data->hook.t.app.app_progress); s->init_data->hook.t.app.app_progress);
s->app_progress_hook = s->init_data->hook.t.app.app_progress; s->app_progress_hook = s->init_data->hook.t.app.app_progress;
/* the hook parser only accepts known sub states of the protocol */
s->sub_state = s->init_data->hook.t.app.sub_state;
return 0; return 0;
} }
@ -4187,6 +4189,7 @@ static int AddAppPolicySignature(struct DetectFirewallAppPolicy *pol)
return -1; return -1;
} }
s->app_progress_hook = pol->progress; s->app_progress_hook = pol->progress;
s->sub_state = pol->sub_state;
s->action = pol->policy.action; s->action = pol->policy.action;
s->action_scope = pol->policy.action_scope; s->action_scope = pol->policy.action_scope;
s->alproto = pol->alproto; s->alproto = pol->alproto;

@ -727,6 +727,10 @@ typedef struct Signature_ {
/** firewall: progress value for this signature */ /** firewall: progress value for this signature */
uint8_t app_progress_hook; uint8_t app_progress_hook;
/** firewall: sub state (transaction type) of the hook on protocols with sub
* states (http2 stream/global, DoH2); 0 when the hook has no sub state.
* Signatures are zero initialized, so unused stays 0. */
uint8_t sub_state;
DetectMatchAddressIPv4 *addr_dst_match4; DetectMatchAddressIPv4 *addr_dst_match4;
DetectMatchAddressIPv4 *addr_src_match4; DetectMatchAddressIPv4 *addr_src_match4;

@ -662,20 +662,35 @@ static void AlertJsonAddFirewall(SCJsonBuilder *jb, const Signature *s)
const char *hook = NULL; const char *hook = NULL;
char hook_string[256]; char hook_string[256];
switch (s->detect_table) { switch (s->detect_table) {
case DETECT_TABLE_APP_FILTER: case DETECT_TABLE_APP_FILTER: {
if (s->flags & SIG_FLAG_TOSERVER) { const uint8_t dir_flag =
hook = AppLayerParserGetStateNameById( (s->flags & SIG_FLAG_TOSERVER) ? STREAM_TOSERVER : STREAM_TOCLIENT;
IPPROTO_TCP, s->alproto, s->app_progress_hook, STREAM_TOSERVER); if (s->sub_state != 0 && AppLayerParserSupportsSubStates(s->alproto)) {
} else { /* sub state rules (http2 stream/global): resolve the state in
hook = AppLayerParserGetStateNameById( * the sub state table and keep the sub state in the name */
IPPROTO_TCP, s->alproto, s->app_progress_hook, STREAM_TOCLIENT); const char *state = AppLayerParserGetSubStateProgressName(
s->alproto, s->sub_state, s->app_progress_hook, dir_flag);
const char *sub_state_name =
AppLayerParserGetSubStateName(s->alproto, s->sub_state);
if (state != NULL && sub_state_name != NULL) {
snprintf(hook_string, sizeof(hook_string), "%s:%s:%s",
AppProtoToString(s->alproto), sub_state_name, state);
hook = hook_string;
} }
if (hook) { }
snprintf(hook_string, sizeof(hook_string), "%s:%s", AppProtoToString(s->alproto), if (hook == NULL) {
hook); /* no sub state, or the sub state lookup failed: fall back to
* the plain per-protocol state name */
hook = AppLayerParserGetStateNameById(
IPPROTO_TCP, s->alproto, s->app_progress_hook, dir_flag);
if (hook != NULL) {
snprintf(hook_string, sizeof(hook_string), "%s:%s",
AppProtoToString(s->alproto), hook);
hook = hook_string; hook = hook_string;
} }
}
break; break;
}
case DETECT_TABLE_PACKET_FILTER: case DETECT_TABLE_PACKET_FILTER:
hook = "packet:filter"; hook = "packet:filter";
break; break;

Loading…
Cancel
Save