HTTP/2 in Suricata 6

While recently working on a malware sample which had some HTTP2 traffic in it. I was surprised that Suricata did not log or alert on any of the traffic for HTTP2, despite having written a rule for the traffic. Turns out, the default configuration included with Suricata 6 have the HTTP/2 parsing disabled.

When it comes to rule writing, the concept of “Overloading” is important and is detailed below.

Configuration Items

When working with HTTP/2 traffic, I would suggest using with at least Suricata version 6.0.4. This version supports all of the required configuration options to enable HTTP/2 logging and alerting.

There are there major settings that need changed.

  1. App-Layer
    app-layer.protocols.http2.enabled
  2. Logging
    outputs.eve-log.types.http2
  3. Overloading
    app-layer.protocols.http2.http1-rules

These settings will get you well on your way to using HTTP/2 on Suricata 6. It should be noted that these settings are slated to be enabled by default with Suricata 7.0 and are already enabled within Suricata 7.0 Beta1

History of HTTP/2 in Suricata

Overall HTTP/2 support within Suricata can be tracked via issue 4201. HTTP/2 support was first added via a commit to Suricata on Aug 7th 2020. In that commit, we can see that the HTTP/2 logging and the protocol parser was marked as “Experimental” and disabled by default:

This initial support for HTTP/2 was eventually included in Suricata 6.0.0 when released on Oct 8 2020.

Overloading

From a rule writer’s perspective, the next major HTTP/2 feature was the ability to “overload” Suricata’s already existing HTTP/1 keywords and buffers with content from HTTP/2 traffic. This allows rules written for HTTP/1 to work on HTTP/2 traffic.

As an example, in HTTP/1 there is a “Host” header which “MUST” be included in every request and represents the “Internet host and port number of the resource being requested”. Suricata, when parsing HTTP/1 traffic will populate this header into the http.host keyword.

However, in HTTP/2 there is no “Host” header, instead it uses the :authority: pseudo-header field to convey the same information.

Now suppose a rule was required which alerted on an HTTP traffic to a specific host, without overloading, two rules would be required.

alert http $HOME_NET any -> any any (msg:"HTTP Outbound - Request to example.com"; flow:established,to_server; http.host; content:"example.com";)
alert http2 $HOME_NET any -> any any (msg:"HTTP Outbound - Request to example.com"; flow:established,to_server; http2.header;  content:":authority: example.com";)

With overloading enabled via the http1-rules configuration item Suricata will use HTTP/1 keywords on HTTP/2 traffic. This config item was introduced via a merge on Sep 6th 2021 which was released as 6.0.4.

With overloading enabled via the http1-rules option in the [suricata configuration]both HTTP1 and HTTP2 traffic can be covered by a single rule.

alert http $HOME_NET any -> any any (msg:"HTTP Outbound - Request to example.com"; flow:established,to_server; http.host; content:"example.com";)

It’s important to note that not all HTTP/1 keywords currently support being overloaded. The expansion of HTTP/1 keywords which can be overloaded with HTTP/2 data continues today and can be tracked via Redmine Issue #4067.

5 Likes