Project

General

Profile

Actions

Bug #7199

open

Suricata 7 no longer logging app-layer metadata in alerts

Added by Antonin Bas 3 months ago. Updated 26 days ago.

Status:
New
Priority:
Normal
Assignee:
Target version:
Affected Versions:
Effort:
Difficulty:
Label:

Description

After upgrading from Suricata 6 to 7, alerts in the eve JSON output no longer seem to include app-layer metadata.
This is what we use to have:

{
  "timestamp": "2023-03-09T20:00:28.210821+0000",
  "flow_id": 627175734391745,
  "in_iface": "antrea-l7-tap0",
  "event_type": "alert",
  "vlan": [
    1
  ],
  "src_ip": "10.10.1.5",
  "src_port": 43352,
  "dest_ip": "10.10.1.4",
  "dest_port": 80,
  "proto": "TCP",
  "alert": {
    "action": "blocked",
    "gid": 1,
    "signature_id": 1,
    "rev": 0,
    "signature": "Reject by AntreaClusterNetworkPolicy:test-l7-ingress",
    "category": "",
    "severity": 3,
    "tenant_id": 1
  },
  "http": {
    "hostname": "10.10.1.4",
    "url": "/admin",
    "http_user_agent": "curl/7.74.0",
    "http_method": "GET",
    "protocol": "HTTP/1.1",
    "length": 0
  },
  "app_proto": "http",
  "flow": {
    "pkts_toserver": 3,
    "pkts_toclient": 1,
    "bytes_toserver": 284,
    "bytes_toclient": 74,
    "start": "2023-03-09T20:00:28.209857+0000" 
  }
}

This is what we have now with Suricata 7.0.6:
{
  "timestamp": "2024-08-26T22:19:16.005590+0000",
  "flow_id": 1147586615954996,
  "in_iface": "antrea-l7-tap0",
  "event_type": "alert",
  "vlan": [
    1
  ],
  "src_ip": "10.10.1.9",
  "src_port": 54728,
  "dest_ip": "10.10.1.10",
  "dest_port": 80,
  "proto": "TCP",
  "pkt_src": "wire/pcap",
  "tenant_id": 1,
  "alert": {
    "action": "blocked",
    "gid": 1,
    "signature_id": 1,
    "rev": 0,
    "signature": "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2",
    "category": "",
    "severity": 3,
    "tenant_id": 1
  },
  "app_proto": "http",
  "direction": "to_server",
  "flow": {
    "pkts_toserver": 3,
    "pkts_toclient": 1,
    "bytes_toserver": 302,
    "bytes_toclient": 78,
    "start": "2024-08-26T22:19:16.005049+0000",
    "src_ip": "10.10.1.9",
    "dest_ip": "10.10.1.10",
    "src_port": 54728,
    "dest_port": 80
  }
}

The first output was captured with Suricata 6 a while back, but the rules were essentially the same. These are the rules I am using now:
reject ip any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; flow: to_server, established; sid: 1;)
pass http any any -> any any (msg: "Allow http by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; http.uri; content:"/api/v2/"; startswith; http.method; content:"GET"; http.host; content:"foo.bar.com"; startswith; endswith; sid: 2;)

And this is the relevant part of the config:

%YAML 1.1
---
outputs:
  - eve-log:
      enabled: yes
      filetype: regular
      filename: eve-%Y-%m-%d.json
      rotate-interval: day
      pcap-file: false
      community-id: false
      community-id-seed: 0
      xff:
        enabled: no
      types:
        - alert:
            tagged-packets: yes
        - http:
            extended: yes
            tagged-packets: yes
        - tls:
            extended: yes

It seems to me that this change, which was not backported to 6, is responsible: https://github.com/OISF/suricata/pull/10876/files, as it added an extra condition for logging app-layer data.

I am assuming that even though the action is "blocked", the expectation is that http data can still be logged here (with the default `metadata` configuration for alerts).

Actions #1

Updated by Antonin Bas 3 months ago

  • Subject changed from Suricata 7 no longer logging app-layer metadata in alerts for blocked requests to Suricata 7 no longer logging app-layer metadata in alerts

I changed the action from "reject" to "alert" in my rule, and the behavior is the same: no app-layer (http) metadata in the alert

{
  "timestamp": "2024-08-06T20:51:58.137656+0000",
  "flow_id": 1709562107260689,
  "in_iface": "antrea-l7-tap0",
  "event_type": "alert",
  "vlan": [
    1
  ],
  "src_ip": "10.10.1.2",
  "src_port": 51350,
  "dest_ip": "10.10.1.3",
  "dest_port": 80,
  "proto": "TCP",
  "pkt_src": "wire/pcap",
  "tenant_id": 1,
  "alert": {
    "action": "allowed",
    "gid": 1,
    "signature_id": 1,
    "rev": 0,
    "signature": "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2",
    "category": "",
    "severity": 3,
    "tenant_id": 1
  },
  "app_proto": "http",
  "direction": "to_server",
  "flow": {
    "pkts_toserver": 3,
    "pkts_toclient": 1,
    "bytes_toserver": 291,
    "bytes_toclient": 78,
    "start": "2024-08-06T20:51:58.135894+0000",
    "src_ip": "10.10.1.2",
    "dest_ip": "10.10.1.3",
    "src_port": 51350,
    "dest_port": 80
  }
}
Actions #2

Updated by Antonin Bas 3 months ago · Edited

Sorry for the additional update.
My guess is that because there is no match on any http attribute, the alert doesn't include a tx_id and no app-layer data is logged.
If I change my rule to

alert http any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; http.method; content:"GET"; sid: 1;)

With a match on the HTTP method, the JSON alert does contain the "http" section.
(If I match on "http" only, without the "http.method" matcher, then I still don't get the app-layer data, which is puzzling to me)

But these questions remain:
  1. Is this the intended behavior? The protocol is detected as http but there is no app-layer data.
  2. Should this behavioral change between Suricata 6 and 7 be documented?
Actions #3

Updated by Juliana Fajardini Reichow about 2 months ago · Edited

Thanks for your report, we'll create a suricata-verify test to try to reproduce it, and add `engine-analysis` checks - which should help in understanding how the engine interprets these rules.

If you have any pcap that you could share, this would help with reproducing the bug, too ;)

One thing to note is that for the first rule shared:

reject ip any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; flow: to_server, established; sid: 1;)

As this is an ip rule, here it would be expected not to see app-layer metadata with any alerts generated.

Actions #4

Updated by Philippe Antoine about 2 months ago

For the configuration, is this IPS mode with stream.inline = true ?

Actions #5

Updated by Philippe Antoine about 2 months ago

What about reject http any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; flow: to_server, established; dsize: >0; sid: 1;)

Actions #6

Updated by Antonin Bas about 2 months ago

Thanks for the replies.

@Philippe Antoine Changing the rule to an http rule and adding the `dsize: >0` matcher didn't change the behavior (still no app-layer metadata in the logs). It's only when I use a matcher that actually requires parsing the HTTP request (e.g., `http.method; content:"GET"`) that the app-layer metadata is included in the logs (but then the connection hangs, with apparently no TCP RST). When said like this, it makes perfect sense of course :), but it's the change of behavior between Suricata 6 and 7 that was puzzling me, and I wasn't sure whether it was intentional. Also the HTTP data should be "available" as it is required by the other rule (the `pass` rule), which is probably why it was showing up with Suricata 6?

This is the log with the rule you suggested:

{"timestamp":"2024-08-27T17:27:04.616964+0000","flow_id":105949864071100,"in_iface":"antrea-l7-tap0","event_type":"alert","vlan":[1],"src_ip":"10.10.1.3","src_port":55718,"dest_ip":"10.10.1.2","dest_port":80,"proto":"TCP","pkt_src":"wire/pcap","tenant_id":1,"alert":{"action":"blocked","gid":1,"signature_id":1,"rev":0,"signature":"Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2","category":"","severity":3,"tenant_id":1},"app_proto":"http","direction":"to_server","flow":{"pkts_toserver":3,"pkts_toclient":1,"bytes_toserver":291,"bytes_toclient":78,"start":"2024-08-27T17:27:04.614492+0000","src_ip":"10.10.1.3","dest_ip":"10.10.1.2","src_port":55718,"dest_port":80}}
# cat /etc/suricata/rules/antrea-l7-networkpolicy-1.rules
reject http any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; flow: to_server, established; dsize: >0; sid: 1;)
pass http any any -> any any (msg: "Allow http by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; http.uri; content:"/api/v2/"; startswith; http.method; content:"GET"; http.host; content:"foo.bar.com"; startswith; endswith; sid: 2;)

Yes, this is IPS mode. We use the default configuration for `stream.inline`:

# suricata --dump-config | grep -i stream.inline
stream.inline = auto

@Juliana Fajardini Reichow It's just an HTTP GET request generated with curl, but I am happy to provide a pcap. Should I just capture with tcpdump on the tap interface?

Actions #7

Updated by Antonin Bas about 2 months ago

  • Description updated (diff)
Actions #8

Updated by Philippe Antoine about 2 months ago

The change you pointed is indeed the right one : https://github.com/OISF/suricata/pull/10876/files

Before that, we always logged transaction id 0 for an alert which did not have transaction keywords...
Now, we try to look the latest transaction, but only for stream alerts.
Maybe the best hack is to use a negated content (even if it is redundant with the previous rule)

reject http any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/ingress-allow-http-request-to-api-v2"; flow: to_server, established; http.uri; content:!"/api/v2/"; startswith; sid: 1;)

But this rule will not fire on non-HTTP traffic

Actions #9

Updated by Antonin Bas about 2 months ago

@Philippe Antoine We need a "catch-all" default reject rule for all the IP traffic that is not covered by the protocol-specific pass rules.

Based on your comment, it sounds like the "new" behavior is the expected one, which makes sense to me. And I guess just using protocol detection and checking for the HTTP protocol (`reject http ...` instead of `reject ip ...`) is not enough to make it a stream alert? This is the one thing that's a bit confusing to me but it's probably just lack of familiarity with Suricata.

Thanks for the follow-up and feel free to close this issue if appropriate.

Actions #10

Updated by Philippe Antoine about 2 months ago

And I guess just using protocol detection and checking for the HTTP protocol (`reject http ...` instead of `reject ip ...`) is not enough to make it a stream alert?

Maybe we could add a new feature/keyword like try_to_log_some_tx_anyways
This keyword would try to make the rule behave as before.

The difficulty here is that this rule alerts on one packet, and one packet may have 0, 1, or multiple transactions associated to it

Actions #11

Updated by Philippe Antoine about 2 months ago

Or "config:logging force, type tx, scope tx; "

Actions #12

Updated by Juliana Fajardini Reichow 26 days ago

Finally an SV, thanks for the offer of submitting a pcap, created one myself - though a bit lazy to do a full clean-up.

Used 4 of the rules indicated here, and showed how it was, and how it is now.

https://github.com/OISF/suricata-verify/pull/2069

Actions

Also available in: Atom PDF