Bug #8944
openfirewall: auto-accept-prior-states not honored when a same-hook drop rule leads the candidate list
Description
In firewall mode, the "auto-accept prior states" notation (accept:... proto:<hook) is documented to accept the target hook and all hooks before it. This does not hold when a lower-SID drop rule at the same target hook has a prefilter that matches the traffic: that drop rule becomes the list-leading firewall candidate, the prior hook is then treated as uncovered ("missing fw rules at list start"), and the flow is dropped by the default app policy at the prior hook -- before the drop rule is ever evaluated.
Net effect: the intended per-SNI drop rule never fires (no alert), and the flow is instead terminated by the default policy. The block still happens, but for the wrong reason and without the rule's alert, and it depends entirely on the default policy being DROP rather than on the authored rule.
Steps to reproduce¶
Firewall ruleset (no explicit accept:hook tls:client_in_progress):
accept:hook tcp:all $HOME_NET any <> $EXTERNAL_NET any (flow:not_established; sid:1021;) accept:hook tcp:all $HOME_NET any <> $EXTERNAL_NET any (flow:established; sid:1022;) drop:flow tls:client_hello_done $HOME_NET any -> $EXTERNAL_NET any (tls.sni; content:"www.google.com"; endswith; nocase; alert; sid:200;) accept:flow tls:<client_hello_done $HOME_NET any -> $EXTERNAL_NET any (alert; sid:201;)
Replay a TLS session whose SNI is www.google.com (e.g. tests/tls/tls-client-hello-frag-01/dump_mtu300.pcap) in simulated IPS mode:
suricata --simulate-ips -k none -c suricata.yaml \
-r dump_mtu300.pcap --firewall-rules-exclusive firewall.rules
Expected behaviour¶
The SNI matches sid:200, so the flow is dropped by the rule:
event_type: alert,alert.signature_id: 200,alert.action: blocked,firewall.hook: "tls:client_hello_done"- first drop
drop.reason: "firewall rules" flow.alerted: truestats.firewall.drop_reason.rules >= 1,default_app_policy: 0
Actual behaviour¶
sid:200never fires; no alert is generated (flow.alerted: false).- First drop is
drop.reason: "firewall default app policy", followed by"firewall flow drop"for the remaining packets. stats.firewall.drop_reason:rules: 0,default_app_policy: 1,flow_drop: 56.
When the SNI does not match sid:200's prefilter, sid:201 (the < rule) leads the candidate list, its auto-accept covers the prior hook, and the flow is accepted as intended. So the prior-hook auto-accept is only honored when the < rule itself leads the candidate list.
Workaround¶
Add an explicit accept for the prior hook so it is covered regardless of candidate ordering:
accept:hook tls:<client_in_progress $HOME_NET any -> $EXTERNAL_NET any (sid:199;)
With that rule present, sid:200 drops www.google.com (drop.reason: "firewall rules", with the alert) and flow.alerted is true. (The existing ruletype-firewall-04/05-ruleset-vs-sni tests already include such an explicit client_in_progress accept.)
Regression test¶
A suricata-verify test that asserts the expected behaviour (and currently fails, reproducing the bug):
- suricata-verify PR: OISF/suricata-verify#3313
- Test:
tests/firewall/ruletype-firewall-200-sni-lte-prior-hook-bug
VJ Updated by Victor Julien 2 days ago
- Status changed from New to In Progress
- Assignee set to Victor Julien