Rules Examining HTTP Request and Response Messages

The stateful nature of the Snort 3 HTTP inspector provides the ability for rule writers to create detection that targets both an HTTP client request and the HTTP server response to that request. Creating detection to do this simply requires including options that target both data from an HTTP response as well as data from an associated HTTP request.

The following Snort rule is a simple example showcasing what this might look like:

alert http (
    msg:"Rule examining a response and the request associated with that response";
    flow:to_client,established;
    file_data;
    content:"pizza",fast_pattern;
    http_uri;
    content:"/index.php";
    classtype:misc-activity;
)

Here the to_client and file_data declarations tell us that the rule is targeting an HTTP response message, and the http_uri declaration tells Snort to get the request message associated with that response and see if the URI contains that content string.

Note that these kinds of rules must have the fast_pattern set on a response-specific rule option since Snort will always check the response before examining the associated request.

The following is a list of request-specific http_* buffers that can be used in this manner:

  • http_uri
  • http_raw_uri
  • http_cookie
  • http_raw_cookie
  • http_header
  • http_raw_header
  • http_trailer
  • http_raw_trailer
  • http_version
  • http_true_ip

The optional "request" argument

Certain HTTP rule options can apply to either an HTTP request or an HTTP response. For example, the http_header rule option can be used to match HTTP request headers or HTTP response headers. As a result, these rule options also allow for an optional request argument that signifies that the given rule option should apply to the HTTP request if the rule contains other options that examine the HTTP response.

For example, the following rule looks for the string "pizza" in an HTTP response message:

alert http (
    msg:"Rule examining just a response message";
    flow:to_client,established;
    file_data;
    content:"pizza",fast_pattern;
    classtype:misc-activity;
)

If we were to add an http_header match, then Snort would see that we are examining the HTTP response message and thus apply http_header to the response headers:

alert http (
    msg:"Rule examining just a response message";
    flow:to_client,established;
    file_data;
    content:"pizza",fast_pattern;
    http_header;
    content:"User-Agent: bad";
    classtype:misc-activity;
)

The above rule would look for a User-Agent string in the response headers, which likely would not match since "User-Agent" is a request header. However, by adding the request argument to http_header, we tell Snort to instead look at the request headers in the request associated with that particular response:

alert http (
    msg:"Rule examining a response and the request associated with that response";
    flow:to_client,established;
    file_data;
    content:"pizza",fast_pattern;
    http_header:request;
    content:"User-Agent: bad";
    classtype:misc-activity;
)

Note that the request argument is not needed for the http_uri rule shown above because a URI will only apply to request messages.