From: jason taylor Date: Fri, 8 Mar 2024 00:42:27 +0000 (+0000) Subject: doc: update http keyword listing order X-Git-Tag: suricata-8.0.0-beta1~1522 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7de16809ef572f39d32d39d90b0bdb9f8a01a83b;p=thirdparty%2Fsuricata.git doc: update http keyword listing order Ticket: 3025 Signed-off-by: jason taylor --- diff --git a/doc/userguide/rules/http-keywords.rst b/doc/userguide/rules/http-keywords.rst index 28c653c86b..bcc9076876 100644 --- a/doc/userguide/rules/http-keywords.rst +++ b/doc/userguide/rules/http-keywords.rst @@ -55,682 +55,633 @@ Example signature that would alert on the above response. classtype:bad-unknown; sid:30; rev:1;) Request Keywords: - * :ref:`http.uri` - * :ref:`http.uri.raw` - * :ref:`http.method` - * :ref:`http.request_line` - * :ref:`http.request_body` - * :ref:`http.user_agent` - * :ref:`http.host` + * :ref:`file.name` * :ref:`http.accept` - * :ref:`http.accept_lang` * :ref:`http.accept_enc` + * :ref:`http.accept_lang` + * :ref:`http.host` + * :ref:`http.host.raw` + * :ref:`http.method` * :ref:`http.referer` - * :ref:`file.name` + * :ref:`http.request_body` + * :ref:`http.request_header` + * :ref:`http.request_line` + * :ref:`http.uri` + * :ref:`http.uri.raw` + * :ref:`http.user_agent` * :ref:`urilen` Response Keywords: - * :ref:`http.stat_msg` - * :ref:`http.stat_code` - * :ref:`http.response_line` + * :ref:`http.location` * :ref:`http.response_body` + * :ref:`http.response_header` + * :ref:`http.response_line` * :ref:`http.server` - * :ref:`http.location` + * :ref:`http.stat_code` + * :ref:`http.stat_msg` Request or Response Keywords: * :ref:`file.data` - * :ref:`http.content_type` * :ref:`http.content_len` - * :ref:`http.start` - * :ref:`http.protocol` - * :ref:`http.header_names` + * :ref:`http.content_type` + * :ref:`http.cookie` * :ref:`http.header` * :ref:`http.header.raw` - * :ref:`http.cookie` - -.. _http.method: + * :ref:`http.header_names` + * :ref:`http.protocol` + * :ref:`http.start` -http.method ------------ +.. _file.name: -The ``http.method`` keyword matches on the method/verb used in an HTTP request. -HTTP request methods can be any of the following: +file.name +--------- -* GET -* POST -* HEAD -* OPTIONS -* PUT -* DELETE -* TRACE -* CONNECT -* PATCH +The ``file.name`` keyword can be used with HTTP requests. -It is possible to use any of the :doc:`payload-keywords` with the ``http.method`` keyword. +It is possible to use any of the :doc:`payload-keywords` with the +``file.name`` keyword. Example HTTP Request:: - GET /index.html HTTP/1.1 + GET /picture.jpg HTTP/1.1 User-Agent: Mozilla/5.0 Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Example"; \ - flow:established,to_server; :example-rule-options:`http.method; \ - content:"GET";` classtype:bad-unknown; sid:2; rev:1;) - -.. _rules-http-uri-normalization: - -.. _http.uri: - -http.uri --------- - -Matching on the HTTP URI buffer has two options in Suricata, the ``http.uri`` -and the ``http.uri.raw`` sticky buffers. + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP file.name Example"; \ + flow:established,to_client; :example-rule-options:`file.name; \ + content:"picture.jpg";` classtype:bad-unknown; sid:129; rev:1;) -It is possible to use any of the :doc:`payload-keywords` with both ``http.uri`` -keywords. +.. note:: Additional information can be found at :doc:`file-keywords` -The ``http.uri`` keyword normalizes the URI buffer. For example, if a URI has two -leading ``//``, Suricata will normalize the URI to a single leading ``/``. +.. _http.accept: -Normalization Example:: +http.accept +----------- - GET //index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - Host: suricata.io +The ``http.accept`` keyword is used to match on the Accept field that +can be present in HTTP request headers. -In this case :example-rule-emphasis:`//index.html` would be normalized to -:example-rule-emphasis:`/index.html`. +It is possible to use any of the :doc:`payload-keywords` with the +``http.accept`` keyword. -Normalized HTTP Request Example:: +Example HTTP Request:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 + Accept: */* Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP URI Example"; \ - flow:established,to_server; :example-rule-options:`http.uri; \ - content:"/index.html";` bsize:11; classtype:bad-unknown; sid:3; rev:1;) - -.. _http.uri.raw: - -http.uri.raw ------------- - -The ``http.uri.raw`` buffer matches on HTTP URI content but does not -have any normalization performed on the buffer contents. -(see :ref:`rules-http-uri-normalization`) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Accept Example"; \ + flow:established,to_server; :example-rule-options:`http.accept; \ + content:"*/*";` bsize:3; classtype:bad-unknown; sid:91; rev:1;) -Abnormal HTTP Request Example:: +.. note:: ``http.accept`` does not include the leading space or trailing \\r\\n - GET //index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - Host: suricata.io +.. _http.accept_enc: -.. container:: example-rule +http.accept_enc +--------------- - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP URI Raw Example"; \ - flow:established,to_server; :example-rule-options:`http.uri.raw; \ - content:"//index.html";` bsize:12; classtype:bad-unknown; sid:4; rev:1;) +The ``http.accept_enc`` keyword is used to match on the Accept-Encoding field +that can be present in HTTP request headers. -.. note:: The ``http.uri.raw`` keyword/buffer does not allow for spaces. +It is possible to use any of the :doc:`payload-keywords` with the +``http.accept_enc`` keyword. -Example Request:: +Example HTTP Request:: - GET /example spaces HTTP/1.1 + GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 + Accept-Encoding: gzip, deflate Host: suricata.io -``http.uri.raw`` would be populated with :example-rule-header:`/example` - -:ref:`http.protocol` would be populated with :example-rule-header:`spaces HTTP/1.1` +.. container:: example-rule -Reference: `https://redmine.openinfosecfoundation.org/issues/2881 `_ + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Accept-Encoding Example"; \ + flow:established,to_server; :example-rule-options:`http.accept_enc; \ + content:"gzip, deflate";` bsize:13; classtype:bad-unknown; sid:92; rev:1;) -.. _urilen: +.. note:: ``http.accept_enc`` does not include the leading space or trailing + \\r\\n -urilen ------- +.. _http.accept_lang: -The ``urilen`` keyword is used to match on the length of the normalized request -URI. It is possible to use the ``<`` and ``>`` operators, which -indicate respectively *less than* and *larger than*. +http.accept_lang +---------------- -urilen uses an :ref:`unsigned 64-bit integer `. +The ``http.accept_lang`` keyword is used to match on the Accept-Language field +that can be present in HTTP request headers. -The ``urilen`` keyword does not require a content match on the :ref:`http.uri` -buffer or the :ref:`http.uri.raw` buffer. +It is possible to use any of the :doc:`payload-keywords` with the +``http.accept_lang`` keyword. Example HTTP Request:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 + Accept-Language: en-US Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request"; \ - flow:established,to_server; :example-rule-options:`urilen:11;` \ - http.method; content:"GET"; classtype:bad-unknown; sid:40; rev:1;) - -The above signature would match on any HTTP GET request that has a URI -length of 11, regardless of the content or structure of the URI. - -The following signatures would all alert on the example request above as well -and show the different ``urilen`` options. - -.. container:: example-rule - - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"urilen greater than 10"; \ - flow:established,to_server; :example-rule-options:`urilen:>10;` \ - classtype:bad-unknown; sid:41; rev:1;) - - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"urilen less than 12"; \ - flow:established,to_server; :example-rule-options:`urilen:<12;` \ - classtype:bad-unknown; sid:42; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Accept-Encoding Example"; \ + flow:established,to_server; :example-rule-options:`http.accept_lang; \ + content:"en-US";` bsize:5; classtype:bad-unknown; sid:93; rev:1;) - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"urilen greater/less than \ - example"; flow:established,to_server; :example-rule-options:`urilen:10<>12;` \ - classtype:bad-unknown; sid:43; rev:1;) +.. note:: ``http.accept_lang`` does not include the leading space or + trailing \\r\\n -.. _http.protocol: +.. _http.connection: -http.protocol -------------- +http.connection +--------------- -The ``http.protocol`` keyword is used to match on the protocol field that is -contained in HTTP requests and responses. +The ``http.connection`` keyword is used to match on the Connection field that +can be present in HTTP request headers. It is possible to use any of the :doc:`payload-keywords` with the -``http.protocol`` keyword. - -.. note:: ``http.protocol`` does not include the leading space or trailing \\r\\n +``http.connection`` keyword. Example HTTP Request:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 + Accept-Language: en-US Host: suricata.io + Connection: Keep-Alive .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Protocol Example"; \ - flow:established,to_server; :example-rule-options:`http.protocol; \ - content:"HTTP/1.1";` bsize:9; classtype:bad-unknown; sid:50; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Connection Example"; \ + flow:established,to_server; :example-rule-options:`http.connection; \ + content:"Keep-Alive";` bsize:10; classtype:bad-unknown; sid:94; rev:1;) -.. _http.request_line: +.. note:: ``http.connection`` does not include the leading space or trailing + \\r\\n -http.request_line ------------------ +.. _http.host: -The ``http.request_line`` keyword is used to match on the entire contents of -the HTTP request line. +http.host +--------- -Example HTTP Request:: +Matching on the HTTP host name has two options in Suricata, the ``http.host`` +and the ``http.host.raw`` sticky buffers. + +It is possible to use any of the :doc:`payload-keywords` with both ``http.host`` +keywords. + +.. note:: The ``http.host`` keyword normalizes the host header contents. If a + host name has uppercase characters, those would be changed to lowercase. + +Normalization Example:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 - Host: suricata.io + Host: SuRiCaTa.Io + +In the above example the host buffer would contain `suricata.io`. .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Example"; \ - flow:established,to_server; :example-rule-options:`http.request_line; \ - content:"GET /index.html HTTP/1.1";` bsize:24; classtype:bad-unknown; \ - sid:60; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Host Example"; \ + flow:established,to_server; :example-rule-options:`http.host; \ + content:"suricata.io";` bsize:11; classtype:bad-unknown; sid:123; rev:1;) -.. note:: ``http.request_line`` does not include the trailing \\r\\n +.. note:: The ``nocase`` keyword is no longer allowed since the host names + are normalized to contain only lowercase letters. -.. _http.header: +.. note:: ``http.host`` does not contain the port associated with the host + (i.e. suricata.io:1234). To match on the host and port or negate a host + and port use :ref:`http.host.raw`. -http.header ------------ +.. note:: ``http.host`` does not include the leading space or trailing \\r\\n -Matching on HTTP headers has two options in Suricata, the ``http.header`` -and the ``http.header.raw``. +.. note:: The ``http.host`` and ``http.host.raw`` buffers are populated + from either the URI (if the full URI is present in the request like + in a proxy request) or the HTTP Host header. If both are present, the + URI is used. -It is possible to use any of the :doc:`payload-keywords` with both -``http.header`` keywords. - -The ``http.header`` keyword normalizes the header contents. For example if -header contents contain trailing white-space or tab characters, those would be -removed. - -To match on non-normalized header data, use the :ref:`http.header.raw` keyword. +.. note:: If a request contains multiple "Host" headers, the values will be + concatenated in the ``http.host`` and ``http.host.raw`` + buffers, in the order seen from top to bottom, with a comma and space + (", ") between each of them. -Normalization Example:: +Example Duplicate Host Header Request:: GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 \r\n + User-Agent: Chrome/2.0 + Cookie: PHPSESSION=123 Host: suricata.io + Host: oisf.net -Would be normalized to :example-rule-emphasis:`Mozilla/5.0\\r\\n` +.. container:: example-rule -Example HTTP Request:: + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Two Host Example"; \ + flow:established,to_server; :example-rule-options:`http.host; \ + content:"suricata.io, oisf.net";` classtype:bad-unknown; sid:125; rev:1;) - GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - Host: suricata.io +.. _http.host.raw: -.. container:: example-rule +http.host.raw +------------- - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Example 1"; \ - flow:established,to_server; :example-rule-options:`http.header; \ - content:"User-Agent|3a 20|Mozilla/5.0|0d 0a|";` classtype:bad-unknown; \ - sid:70; rev:1;) +The ``http.host.raw`` buffer matches on HTTP host content but does not have +any normalization performed on the buffer contents (see :ref:`http.host`) - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Example 2"; \ - flow:established,to_server; :example-rule-options:`http.header; \ - content:"Host|3a 20|suricata.io|0d 0a|";` classtype:bad-unknown; \ - sid:71; rev:1;) +Example HTTP Request:: - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Example 3"; \ - flow:established,to_server; :example-rule-options:`http.header; \ - content:"User-Agent|3a 20|Mozilla/5.0|0d 0a|"; startswith; \ - content:"Host|3a 20|suricata.io|0d 0a|";` classtype:bad-unknown; \ - sid:72; rev:1;) + GET /index.html HTTP/1.1 + User-Agent: Mozilla/5.0 + Host: SuRiCaTa.Io:8445 -.. note:: There are headers that will not be included in the ``http.header`` - buffer, specifically the :ref:`http.cookie` buffer. +.. container:: example-rule -.. note:: If there are multiple values for the same header name, they are - concatenated with a comma and space (", ") between each value. - More information can be found in RFC 2616 - ``_ + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Host Raw Example"; \ + flow:established,to_server; :example-rule-options:`http.host.raw; \ + content:"SuRiCaTa.Io|3a|8445";` bsize:16; classtype:bad-unknown; sid:124; rev:1;) -.. _http.header.raw: +.. note:: ``http.host.raw`` does not include the leading space or trailing \\r\\n -http.header.raw ---------------- +.. note:: The ``http.host`` and ``http.host.raw`` buffers are populated + from either the URI (if the full URI is present in the request like + in a proxy request) or the HTTP Host header. If both are present, the + URI is used. -The ``http.header.raw`` buffer matches on HTTP header content but does not have -any normalization performed on the buffer contents (see :ref:`http.header`) +.. note:: If a request contains multiple "Host" headers, the values will be + concatenated in the ``http.host`` and ``http.host.raw`` buffers, in the + order seen from top to bottom, with a comma and space (", ") between each + of them. -Abnormal HTTP Header Example:: +Example Duplicate Host Header Request:: GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - User-Agent: Chrome + User-Agent: Chrome/2.0 + Cookie: PHPSESSION=123 Host: suricata.io + Host: oisf.net .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Raw Example"; \ - flow:established,to_server; :example-rule-options:`http.header.raw; \ - content:"User-Agent|3a 20|Mozilla/5.0|0d 0a|"; \ - content:"User-Agent|3a 20|Chrome|0d 0a|";` classtype:bad-unknown; sid:73; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Two Host Example"; \ + flow:established,to_server; :example-rule-options:`http.host.raw; \ + content:"suricata.io, oisf.net";` classtype:bad-unknown; sid:125; rev:1;) -.. _http.cookie: +.. _http.method: -http.cookie +http.method ----------- -The ``http.cookie`` keyword is used to match on the cookie field that can be -present in HTTP request (Cookie) or HTTP response (Set-Cookie) headers. - -It is possible to use any of the :doc:`payload-keywords` with both ``http.header`` -keywords. +The ``http.method`` keyword matches on the method/verb used in an HTTP request. +HTTP request methods can be any of the following: -.. note:: Cookies are passed in HTTP headers but Suricata extracts the cookie - data to ``http.cookie`` and will not match cookie content put in the - :ref:`http.header` sticky buffer. +* GET +* POST +* HEAD +* OPTIONS +* PUT +* DELETE +* TRACE +* CONNECT +* PATCH -.. note:: ``http.cookie`` does not include the leading space or trailing \\r\\n +It is possible to use any of the :doc:`payload-keywords` with the ``http.method`` keyword. Example HTTP Request:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 - Cookie: PHPSESSION=123 Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Cookie Example"; \ - flow:established,to_server; :example-rule-emphasis:`http.cookie; \ - content:"PHPSESSIONID=123";` bsize:14; classtype:bad-unknown; sid:80; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Example"; \ + flow:established,to_server; :example-rule-options:`http.method; \ + content:"GET";` classtype:bad-unknown; sid:2; rev:1;) -.. _http.user_agent: +.. _http.referer: -http.user_agent ---------------- +http.referer +------------ -The ``http.user_agent`` keyword is used to match on the User-Agent field that +The ``http.referer`` keyword is used to match on the Referer field that can be present in HTTP request headers. It is possible to use any of the :doc:`payload-keywords` with the -``http.user_agent`` keyword. +``http.referer`` keyword. Example HTTP Request:: - GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - Cookie: PHPSESSION=123 + GET / HTTP/1.1 Host: suricata.io + Referer: https://suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP User-Agent Example"; \ - flow:established,to_server; :example-rule-options:`http.user_agent; \ - content:"Mozilla/5.0";` bsize:11; classtype:bad-unknown; sid:90; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Referer Example"; \ + flow:established,to_server; :example-rule-options:`http.referer; \ + content:"http|3a 2f 2f|suricata.io";` bsize:19; classtype:bad-unknown; \ + sid:200; rev:1;) -.. note:: ``http.user_agent`` does not include the leading space or trailing +.. note:: ``http.referer`` does not include the leading space or trailing \\r\\n -.. note:: Using the ``http.user_agent`` generally provides better performance - than using :ref:`http.header`. +.. _http.request_body: -.. note:: If a request contains multiple "User-Agent" headers, the values will - be concatenated in the ``http.user_agent`` buffer, in the order seen from - top to bottom, with a comma and space (", ") between each of them. +http.request_body +----------------- -Example Duplicate User-Agent Header Request:: +The ``http.request_body`` keyword is used to match on the HTTP request body +that can be present in an HTTP request. - GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - User-Agent: Chrome/2.0 - Cookie: PHPSESSION=123 +It is possible to use any of the :doc:`payload-keywords` with the +``http.request_body`` keyword. + +Example HTTP Request:: + + POST /suricata.php HTTP/1.1 + Content-Type: application/x-www-form-urlencoded Host: suricata.io + Content-Length: 23 + Connection: Keep-Alive + + Suricata request body .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP User-Agent Example"; \ - flow:established,to_server; :example-rule-options:`http.user_agent; \ - content:"Mozilla/5.0, Chrome/2.0";` bsize:23; classtype:bad-unknown; sid:90; \ - rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Body Example"; \ + flow:established,to_server; :example-rule-options:`http.request_body; \ + content:"Suricata request body";` classtype:bad-unknown; sid:115; rev:1;) -.. _http.accept: +.. note:: How much of the request/client body is inspected is controlled + in the :ref:`libhtp configuration section + ` via the ``request-body-limit`` + setting. -http.accept ------------ +.. note:: ``http.request_body`` replaces the previous keyword name, + ``http_client_body``. ``http_client_body`` can still be used but it is + recommended that rules be converted to use ``http.request_body``. -The ``http.accept`` keyword is used to match on the Accept field that -can be present in HTTP request headers. +.. _http.request_header: + +http.request_header +------------------- + +The ``http.request_header`` keyword is used to match on the name and value +of a HTTP/1 or HTTP/2 request. It is possible to use any of the :doc:`payload-keywords` with the -``http.accept`` keyword. +``http.request_header`` keyword. -Example HTTP Request:: +For HTTP/2, the header name and value get concatenated by ": " (colon and space). +The colon and space are commonly noted with the hexadecimal format `|3a 20|` +within signatures. + +To detect if an HTTP/2 header name contains a ":" (colon), the keyword +:ref:`http2.header_name` can be used. + +Example HTTP/1 Request:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 - Accept: */* Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Accept Example"; \ - flow:established,to_server; :example-rule-options:`http.accept; \ - content:"*/*";` bsize:3; classtype:bad-unknown; sid:91; rev:1;) - -.. note:: ``http.accept`` does not include the leading space or trailing \\r\\n + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Example"; \ + flow:established,to_server; :example-rule-options:`http.request_header; \ + content:"Host|3a 20|suricata.io";` classtype:bad-unknown; sid:126; rev:1;) -.. _http.accept_enc: +.. note:: ``http.request_header`` does not include the trailing \\r\\n -http.accept_enc ---------------- +.. _http.request_line: -The ``http.accept_enc`` keyword is used to match on the Accept-Encoding field -that can be present in HTTP request headers. +http.request_line +----------------- -It is possible to use any of the :doc:`payload-keywords` with the -``http.accept_enc`` keyword. +The ``http.request_line`` keyword is used to match on the entire contents of +the HTTP request line. Example HTTP Request:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 - Accept-Encoding: gzip, deflate Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Accept-Encoding Example"; \ - flow:established,to_server; :example-rule-options:`http.accept_enc; \ - content:"gzip, deflate";` bsize:13; classtype:bad-unknown; sid:92; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Example"; \ + flow:established,to_server; :example-rule-options:`http.request_line; \ + content:"GET /index.html HTTP/1.1";` bsize:24; classtype:bad-unknown; \ + sid:60; rev:1;) -.. note:: ``http.accept_enc`` does not include the leading space or trailing - \\r\\n +.. note:: ``http.request_line`` does not include the trailing \\r\\n -.. _http.accept_lang: +.. _rules-http-uri-normalization: -http.accept_lang ----------------- +.. _http.uri: -The ``http.accept_lang`` keyword is used to match on the Accept-Language field -that can be present in HTTP request headers. +http.uri +-------- -It is possible to use any of the :doc:`payload-keywords` with the -``http.accept_lang`` keyword. +Matching on the HTTP URI buffer has two options in Suricata, the ``http.uri`` +and the ``http.uri.raw`` sticky buffers. -Example HTTP Request:: +It is possible to use any of the :doc:`payload-keywords` with both ``http.uri`` +keywords. - GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - Accept-Language: en-US - Host: suricata.io - -.. container:: example-rule - - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Accept-Encoding Example"; \ - flow:established,to_server; :example-rule-options:`http.accept_lang; \ - content:"en-US";` bsize:5; classtype:bad-unknown; sid:93; rev:1;) - -.. note:: ``http.accept_lang`` does not include the leading space or - trailing \\r\\n - -.. _http.connection: +The ``http.uri`` keyword normalizes the URI buffer. For example, if a URI has two +leading ``//``, Suricata will normalize the URI to a single leading ``/``. -http.connection ---------------- +Normalization Example:: -The ``http.connection`` keyword is used to match on the Connection field that -can be present in HTTP request headers. + GET //index.html HTTP/1.1 + User-Agent: Mozilla/5.0 + Host: suricata.io -It is possible to use any of the :doc:`payload-keywords` with the -``http.connection`` keyword. +In this case :example-rule-emphasis:`//index.html` would be normalized to +:example-rule-emphasis:`/index.html`. -Example HTTP Request:: +Normalized HTTP Request Example:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 - Accept-Language: en-US Host: suricata.io - Connection: Keep-Alive .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Connection Example"; \ - flow:established,to_server; :example-rule-options:`http.connection; \ - content:"Keep-Alive";` bsize:10; classtype:bad-unknown; sid:94; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP URI Example"; \ + flow:established,to_server; :example-rule-options:`http.uri; \ + content:"/index.html";` bsize:11; classtype:bad-unknown; sid:3; rev:1;) -.. note:: ``http.connection`` does not include the leading space or trailing - \\r\\n +.. _http.uri.raw: -.. _http.content_type: +http.uri.raw +------------ -http.content_type ------------------ +The ``http.uri.raw`` buffer matches on HTTP URI content but does not +have any normalization performed on the buffer contents. +(see :ref:`rules-http-uri-normalization`) -The ``http.content_type`` keyword is used to match on the Content-Type field that -can be present in HTTP request or response headers. Use ``flow:to_server`` or -``flow:to_client`` to force inspection of the request or response respectively. +Abnormal HTTP Request Example:: -It is possible to use any of the :doc:`payload-keywords` with the -``http.content_type`` keyword. + GET //index.html HTTP/1.1 + User-Agent: Mozilla/5.0 + Host: suricata.io -Example HTTP Request:: +.. container:: example-rule - POST /suricata.php HTTP/1.1 - Content-Type: multipart/form-data; boundary=---------------123 - Host: suricata.io - Content-Length: 100 - Connection: Keep-Alive + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP URI Raw Example"; \ + flow:established,to_server; :example-rule-options:`http.uri.raw; \ + content:"//index.html";` bsize:12; classtype:bad-unknown; sid:4; rev:1;) -Example HTTP Response:: +.. note:: The ``http.uri.raw`` keyword/buffer does not allow for spaces. - HTTP/1.1 200 OK - Content-Type: text/html - Server: nginx/0.8.54 - Connection: Close +Example Request:: -.. container:: example-rule + GET /example spaces HTTP/1.1 + User-Agent: Mozilla/5.0 + Host: suricata.io - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Content-Type Request \ - Example"; flow:established,to_server; :example-rule-options:`http.content_type; \ - content:"multipart/form-data|3b 20|";` startswith; classtype:bad-unknown; \ - sid:95; rev:1;) +``http.uri.raw`` would be populated with :example-rule-header:`/example` - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Content-Type Response \ - Example"; flow:established,to_client; :example-rule-options:`http.content_type; \ - content:"text/html";` bsize:9; classtype:bad-unknown; sid:96; rev:1;) +:ref:`http.protocol` would be populated with :example-rule-header:`spaces HTTP/1.1` -.. note:: ``http.content_type`` does not include the leading space or trailing - \\r\\n +Reference: `https://redmine.openinfosecfoundation.org/issues/2881 `_ -.. _http.content_len: +.. _http.user_agent: -http.content_len ----------------- +http.user_agent +--------------- -The ``http.content_len`` keyword is used to match on the Content-Length field that -can be present in HTTP request or response headers. Use ``flow:to_server`` or -``flow:to_client`` to force inspection of the request or response respectively. +The ``http.user_agent`` keyword is used to match on the User-Agent field that +can be present in HTTP request headers. It is possible to use any of the :doc:`payload-keywords` with the -``http.content_len`` keyword. +``http.user_agent`` keyword. Example HTTP Request:: - POST /suricata.php HTTP/1.1 - Content-Type: multipart/form-data; boundary=---------------123 + GET /index.html HTTP/1.1 + User-Agent: Mozilla/5.0 + Cookie: PHPSESSION=123 Host: suricata.io - Content-Length: 100 - Connection: Keep-Alive -Example HTTP Response:: +.. container:: example-rule - HTTP/1.1 200 OK - Content-Type: text/html - Server: nginx/0.8.54 - Connection: Close - Content-Length: 20 + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP User-Agent Example"; \ + flow:established,to_server; :example-rule-options:`http.user_agent; \ + content:"Mozilla/5.0";` bsize:11; classtype:bad-unknown; sid:90; rev:1;) -.. container:: example-rule +.. note:: ``http.user_agent`` does not include the leading space or trailing + \\r\\n - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Content-Length Request \ - Example"; flow:established,to_server; :example-rule-options:`http.content_len; \ - content:"100";` bsize:3; classtype:bad-unknown; sid:97; rev:1;) +.. note:: Using the ``http.user_agent`` generally provides better performance + than using :ref:`http.header`. - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Content-Length Response \ - Example"; flow:established,to_client; :example-rule-options:`http.content_len; \ - content:"20";` bsize:2; classtype:bad-unknown; sid:98; rev:1;) +.. note:: If a request contains multiple "User-Agent" headers, the values will + be concatenated in the ``http.user_agent`` buffer, in the order seen from + top to bottom, with a comma and space (", ") between each of them. -To do numeric evaluation of the content length, :ref:`byte_test` can be used. +Example Duplicate User-Agent Header Request:: -If we want to match on an HTTP request content length equal to and greater -than 100 we could use the following signature. + GET /index.html HTTP/1.1 + User-Agent: Mozilla/5.0 + User-Agent: Chrome/2.0 + Cookie: PHPSESSION=123 + Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Content-Length Request \ - Byte Test Example"; flow:established,to_server; \ - :example-rule-options:`http.content_len; byte_test:0,>=,100,0,string,dec;` \ - classtype:bad-unknown; sid:99; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP User-Agent Example"; \ + flow:established,to_server; :example-rule-options:`http.user_agent; \ + content:"Mozilla/5.0, Chrome/2.0";` bsize:23; classtype:bad-unknown; sid:90; \ + rev:1;) -.. note:: ``http.content_len`` does not include the leading space or trailing - \\r\\n +.. _urilen: -.. _http.referer: +urilen +------ -http.referer ------------- +The ``urilen`` keyword is used to match on the length of the normalized request +URI. It is possible to use the ``<`` and ``>`` operators, which +indicate respectively *less than* and *larger than*. -The ``http.referer`` keyword is used to match on the Referer field that -can be present in HTTP request headers. +urilen uses an :ref:`unsigned 64-bit integer `. -It is possible to use any of the :doc:`payload-keywords` with the -``http.referer`` keyword. +The ``urilen`` keyword does not require a content match on the :ref:`http.uri` +buffer or the :ref:`http.uri.raw` buffer. Example HTTP Request:: - GET / HTTP/1.1 + GET /index.html HTTP/1.1 + User-Agent: Mozilla/5.0 Host: suricata.io - Referer: https://suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Referer Example"; \ - flow:established,to_server; :example-rule-options:`http.referer; \ - content:"http|3a 2f 2f|suricata.io";` bsize:19; classtype:bad-unknown; \ - sid:200; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request"; \ + flow:established,to_server; :example-rule-options:`urilen:11;` \ + http.method; content:"GET"; classtype:bad-unknown; sid:40; rev:1;) -.. note:: ``http.referer`` does not include the leading space or trailing - \\r\\n +The above signature would match on any HTTP GET request that has a URI +length of 11, regardless of the content or structure of the URI. -.. _http.start: +The following signatures would all alert on the example request above as well +and show the different ``urilen`` options. -http.start ----------- +.. container:: example-rule -The ``http.start`` keyword is used to match on the start of an HTTP request -or response. This will contain the request/response line plus the request/response -headers. Use ``flow:to_server`` or ``flow:to_client`` to force inspection of the -request or response respectively. + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"urilen greater than 10"; \ + flow:established,to_server; :example-rule-options:`urilen:>10;` \ + classtype:bad-unknown; sid:41; rev:1;) -It is possible to use any of the :doc:`payload-keywords` with the -``http.start`` keyword. + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"urilen less than 12"; \ + flow:established,to_server; :example-rule-options:`urilen:<12;` \ + classtype:bad-unknown; sid:42; rev:1;) -Example HTTP Request:: + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"urilen greater/less than \ + example"; flow:established,to_server; :example-rule-options:`urilen:10<>12;` \ + classtype:bad-unknown; sid:43; rev:1;) - GET / HTTP/1.1 - Host: suricata.io - Connection: Keep-Alive +.. _http.location: + +http.location +------------- + +The ``http.location`` keyword is used to match on the HTTP response location +header contents. + +It is possible to use any of the :doc:`payload-keywords` with the +``http.location`` keyword. Example HTTP Response:: HTTP/1.1 200 OK Content-Type: text/html Server: nginx/0.8.54 + Location: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Start Request \ - Example"; flow:established,to_server; :example-rule-options:`http.start; \ - content:"POST / HTTP/1.1|0d 0a|Host|0d 0a|Connection|0d 0a 0d 0a|";` \ - classtype:bad-unknown; sid:101; rev:1;) - - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Start Response \ - Example"; flow:established,to_client; :example-rule-options:`http.start; \ - content:"HTTP/1.1 200 OK|0d 0a|Content-Type|0d 0a|Server|0d 0a 0d a0|";` \ - classtype:bad-unknown; sid:102; rev:1;) + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Location Example"; \ + flow:established,to_client; :example-rule-options:`http.location; \ + content:"suricata.io";` bsize:11; classtype:bad-unknown; sid:122; rev:1;) -.. note:: ``http.start`` contains the normalized headers and is terminated by - an extra \\r\\n to indicate the end of the headers. +.. note:: ``http.location`` does not include the leading space or trailing \\r\\n -.. _http.header_names: +.. _http.response_body: -http.header_names ------------------ +http.response_body +------------------ -The ``http.header_names`` keyword is used to match on the names of the headers -in an HTTP request or response. This is useful for checking for a headers -presence, absence and/or header order. Use ``flow:to_server`` or -``flow:to_client`` to force inspection of the request or response respectively. +The ``http.response_body`` keyword is used to match on the HTTP response body. It is possible to use any of the :doc:`payload-keywords` with the -``http.header_names`` keyword. - -Example HTTP Request:: - - GET / HTTP/1.1 - Host: suricata.io - Connection: Keep-Alive +``http.response_body`` keyword. Example HTTP Response:: @@ -738,91 +689,105 @@ Example HTTP Response:: Content-Type: text/html Server: nginx/0.8.54 -Examples to match exactly on header order: + Server response body .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ - Example"; flow:established,to_server; :example-rule-options:`http.header_names; \ - content:"|0d 0a|Host|0d 0a|Connection|0d 0a 0d 0a|";` bsize:22; \ - classtype:bad-unknown; sid:110; rev:1;) + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Response Body \ + Example"; flow:established,to_client; :example-rule-options:`http.response_body; \ + content:"Server response body";` classtype:bad-unknown; sid:120; rev:1;) - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Header Names Response \ - Example"; flow:established,to_client; :example-rule-options:`http.header_names; \ - content:"|0d 0a|Content-Type|0d 0a|Server|0d 0a 0d a0|";` bsize:26; \ - classtype:bad-unknown; sid:111; rev:1;) +.. note:: ``http.response_body`` will match on gzip decoded data just like + :ref:`file.data` does. -Examples to match on header existence: +.. note:: How much of the response/server body is inspected is controlled + in your :ref:`libhtp configuration section + ` via the ``response-body-limit`` + setting. -.. container:: example-rule +.. note:: ``http.response_body`` replaces the previous keyword name, + ``http_server_body``. ``http_server_body`` can still be used but it is + recommended that rules be converted to use ``http.response_body``. - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ - Example 2"; flow:established,to_server; :example-rule-options:`http.header_names; \ - content:"|0d 0a|Host|0d 0a|";` classtype:bad-unknown; sid:112; rev:1;) +.. _http.response_header: - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Header Names Response \ - Example 2"; flow:established,to_client; :example-rule-options:`http.header_names; \ - content:"|0d 0a|Content-Type|0d 0a|";` classtype:bad-unknown; sid:113; rev:1;) +http.response_header +-------------------- -Examples to match on header absence: +The ``http.response_header`` keyword is used to match on the name and value +of an HTTP/1 or HTTP/2 request. + +It is possible to use any of the :doc:`payload-keywords` with the +``http.response_header`` keyword. + +For HTTP/2, the header name and value get concatenated by ": " (colon and space). +The colon and space are commonly noted with the hexadecimal format `|3a 20|` +within signatures. + +To detect if an HTTP/2 header name contains a ":" (colon), the keyword +:ref:`http2.header_name` can be used. + +Example HTTP Response:: + + HTTP/1.1 200 OK + Content-Type: text/html + Server: nginx/0.8.54 + Location: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ - Example 3"; flow:established,to_server; :example-rule-options:`http.header_names; \ - content:!"|0d 0a|User-Agent|0d 0a|";` classtype:bad-unknown; sid:114; rev:1;) + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Response Example"; \ + flow:established,to_client; :example-rule-options:`http.response_header; \ + content:"Location|3a 20|suricata.io";` classtype:bad-unknown; sid:127; rev:1;) - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Header Names Response \ - Example 3"; flow:established,to_client; :example-rule-options:`http.header_names; \ - content:!"|0d 0a|Date|0d 0a|";` classtype:bad-unknown; sid:115; rev:1;) +.. _http.response_line: -Example to check for the ``User-Agent`` header and that the ``Host`` header is -after ``User-Agent`` but not necessarily directly after. +http.response_line +------------------ + +The ``http.response_line`` keyword is used to match on the entire HTTP +response line. + +It is possible to use any of the :doc:`payload-keywords` with the +``http.response_line`` keyword. + +Example HTTP Response:: + + HTTP/1.1 200 OK + Content-Type: text/html + Server: nginx/0.8.54 .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ - Example 4"; flow:established,to_server; :example-rule-options:`http.header_names; \ - content:"|0d 0a|Host|0d 0a|";` content:"User-Agent|0d 0a|"; distance:-2; \ - classtype:bad-unknown; sid:114; rev:1;) + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Response Line \ + Example"; flow:established,to_client; :example-rule-options:`http.response_line; \ + content:"HTTP/1.1 200 OK";` classtype:bad-unknown; sid:119; rev:1;) -.. note:: ``http.header_names`` starts with a \\r\\n and ends with an extra \\r\\n. +.. note:: ``http.response_line`` does not include the trailing \\r\\n -.. _http.request_body: +.. _http.server: -http.request_body ------------------ +http.server +----------- -The ``http.request_body`` keyword is used to match on the HTTP request body -that can be present in an HTTP request. +The ``http.server`` keyword is used to match on the HTTP response server +header contents. It is possible to use any of the :doc:`payload-keywords` with the -``http.request_body`` keyword. - -Example HTTP Request:: +``http.server`` keyword. - POST /suricata.php HTTP/1.1 - Content-Type: application/x-www-form-urlencoded - Host: suricata.io - Content-Length: 23 - Connection: Keep-Alive +Example HTTP Response:: - Suricata request body + HTTP/1.1 200 OK + Content-Type: text/html + Server: nginx/0.8.54 .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Body Example"; \ - flow:established,to_server; :example-rule-options:`http.request_body; \ - content:"Suricata request body";` classtype:bad-unknown; sid:115; rev:1;) - -.. note:: How much of the request/client body is inspected is controlled - in the :ref:`libhtp configuration section - ` via the ``request-body-limit`` - setting. + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Server Example"; flow:established,to_client; :example-rule-options:`http.server; \ + content:"nginx/0.8.54";` bsize:12; classtype:bad-unknown; sid:121; rev:1;) -.. note:: ``http.request_body`` replaces the previous keyword name, - ``http_client_body``. ``http_client_body`` can still be used but it is - recommended that rules be converted to use ``http.request_body``. +.. note:: ``http.server`` does not include the leading space or trailing \\r\\n .. _http.stat_code: @@ -876,16 +841,17 @@ Example HTTP Response:: .. note:: ``http.stat_msg`` will always be empty when used with HTTP/2 -.. _http.response_line: +.. _file.data: -http.response_line ------------------- +file.data +--------- -The ``http.response_line`` keyword is used to match on the entire HTTP -response line. +With ``file.data``, the HTTP response body is inspected, just like +with ``http.response_body``. ``file.data`` also works for HTTP request +body and can be used in protocols other than HTTP. It is possible to use any of the :doc:`payload-keywords` with the -``http.response_line`` keyword. +``file.data`` keyword. Example HTTP Response:: @@ -893,364 +859,401 @@ Example HTTP Response:: Content-Type: text/html Server: nginx/0.8.54 -.. container:: example-rule + Server response body - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Response Line \ - Example"; flow:established,to_client; :example-rule-options:`http.response_line; \ - content:"HTTP/1.1 200 OK";` classtype:bad-unknown; sid:119; rev:1;) +.. container:: example-rule -.. note:: ``http.response_line`` does not include the trailing \\r\\n + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP file.data Example"; \ + flow:established,to_client; :example-rule-options:`file.data; \ + content:"Server response body";` classtype:bad-unknown; sid:128; rev:1;) -.. _http.response_body: +The body of an HTTP response can be very large, therefore the response body is +inspected in definable chunks. -http.response_body ------------------- +How much of the response/server body is inspected is controlled +in the :ref:`libhtp configuration section +` via the ``response-body-limit`` +setting. -The ``http.response_body`` keyword is used to match on the HTTP response body. +.. note:: If the HTTP body is a flash file compressed with 'deflate' or 'lzma', + it can be decompressed and ``file.data`` can match on the decompressed data. + Flash decompression must be enabled under 'libhtp' configuration: -It is possible to use any of the :doc:`payload-keywords` with the -``http.response_body`` keyword. + :: -Example HTTP Response:: + # Decompress SWF files. + # 2 types: 'deflate', 'lzma', 'both' will decompress deflate and lzma + # compress-depth: + # Specifies the maximum amount of data to decompress, + # set 0 for unlimited. + # decompress-depth: + # Specifies the maximum amount of decompressed data to obtain, + # set 0 for unlimited. + swf-decompression: + enabled: yes + type: both + compress-depth: 0 + decompress-depth: 0 - HTTP/1.1 200 OK - Content-Type: text/html - Server: nginx/0.8.54 +.. note:: ``file.data`` replaces the previous keyword name, ``file_data``. + ``file_data`` can still be used but it is recommended that rules be converted + to use ``file.data``. - Server response body +.. note:: If an HTTP body is using gzip or deflate, ``file.data`` will match on + the decompressed data. -.. container:: example-rule +.. note:: Negated matching is affected by the chunked inspection. E.g. + 'content:!" $HOME_NET any (msg:"HTTP Response Body \ - Example"; flow:established,to_client; :example-rule-options:`http.response_body; \ - content:"Server response body";` classtype:bad-unknown; sid:120; rev:1;) +.. note:: Additional information can be found at :doc:`file-keywords` -.. note:: ``http.response_body`` will match on gzip decoded data just like - :ref:`file.data` does. +.. note:: ``file.data`` supports multiple buffer matching, see + :doc:`multi-buffer-matching`. -.. note:: How much of the response/server body is inspected is controlled - in your :ref:`libhtp configuration section - ` via the ``response-body-limit`` - setting. +.. _http.content_len: -.. note:: ``http.response_body`` replaces the previous keyword name, - ``http_server_body``. ``http_server_body`` can still be used but it is - recommended that rules be converted to use ``http.response_body``. +http.content_len +---------------- -.. _http.server: +The ``http.content_len`` keyword is used to match on the Content-Length field that +can be present in HTTP request or response headers. Use ``flow:to_server`` or +``flow:to_client`` to force inspection of the request or response respectively. -http.server ------------ +It is possible to use any of the :doc:`payload-keywords` with the +``http.content_len`` keyword. -The ``http.server`` keyword is used to match on the HTTP response server -header contents. +Example HTTP Request:: -It is possible to use any of the :doc:`payload-keywords` with the -``http.server`` keyword. + POST /suricata.php HTTP/1.1 + Content-Type: multipart/form-data; boundary=---------------123 + Host: suricata.io + Content-Length: 100 + Connection: Keep-Alive Example HTTP Response:: HTTP/1.1 200 OK Content-Type: text/html Server: nginx/0.8.54 + Connection: Close + Content-Length: 20 .. container:: example-rule - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Server Example"; flow:established,to_client; :example-rule-options:`http.server; \ - content:"nginx/0.8.54";` bsize:12; classtype:bad-unknown; sid:121; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Content-Length Request \ + Example"; flow:established,to_server; :example-rule-options:`http.content_len; \ + content:"100";` bsize:3; classtype:bad-unknown; sid:97; rev:1;) -.. note:: ``http.server`` does not include the leading space or trailing \\r\\n + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Content-Length Response \ + Example"; flow:established,to_client; :example-rule-options:`http.content_len; \ + content:"20";` bsize:2; classtype:bad-unknown; sid:98; rev:1;) -.. _http.location: +To do numeric evaluation of the content length, :ref:`byte_test` can be used. -http.location -------------- +If we want to match on an HTTP request content length equal to and greater +than 100 we could use the following signature. -The ``http.location`` keyword is used to match on the HTTP response location -header contents. +.. container:: example-rule -It is possible to use any of the :doc:`payload-keywords` with the -``http.location`` keyword. + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Content-Length Request \ + Byte Test Example"; flow:established,to_server; \ + :example-rule-options:`http.content_len; byte_test:0,>=,100,0,string,dec;` \ + classtype:bad-unknown; sid:99; rev:1;) -Example HTTP Response:: - - HTTP/1.1 200 OK - Content-Type: text/html - Server: nginx/0.8.54 - Location: suricata.io +.. note:: ``http.content_len`` does not include the leading space or trailing + \\r\\n -.. container:: example-rule +.. _http.content_type: - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Location Example"; \ - flow:established,to_client; :example-rule-options:`http.location; \ - content:"suricata.io";` bsize:11; classtype:bad-unknown; sid:122; rev:1;) +http.content_type +----------------- -.. note:: ``http.location`` does not include the leading space or trailing \\r\\n +The ``http.content_type`` keyword is used to match on the Content-Type field that +can be present in HTTP request or response headers. Use ``flow:to_server`` or +``flow:to_client`` to force inspection of the request or response respectively. -.. _http.host: +It is possible to use any of the :doc:`payload-keywords` with the +``http.content_type`` keyword. -http.host ---------- +Example HTTP Request:: -Matching on the HTTP host name has two options in Suricata, the ``http.host`` -and the ``http.host.raw`` sticky buffers. + POST /suricata.php HTTP/1.1 + Content-Type: multipart/form-data; boundary=---------------123 + Host: suricata.io + Content-Length: 100 + Connection: Keep-Alive -It is possible to use any of the :doc:`payload-keywords` with both ``http.host`` -keywords. +Example HTTP Response:: -.. note:: The ``http.host`` keyword normalizes the host header contents. If a - host name has uppercase characters, those would be changed to lowercase. + HTTP/1.1 200 OK + Content-Type: text/html + Server: nginx/0.8.54 + Connection: Close -Normalization Example:: +.. container:: example-rule - GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - Host: SuRiCaTa.Io + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Content-Type Request \ + Example"; flow:established,to_server; :example-rule-options:`http.content_type; \ + content:"multipart/form-data|3b 20|";` startswith; classtype:bad-unknown; \ + sid:95; rev:1;) -In the above example the host buffer would contain `suricata.io`. + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Content-Type Response \ + Example"; flow:established,to_client; :example-rule-options:`http.content_type; \ + content:"text/html";` bsize:9; classtype:bad-unknown; sid:96; rev:1;) -.. container:: example-rule +.. note:: ``http.content_type`` does not include the leading space or trailing + \\r\\n - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Host Example"; \ - flow:established,to_server; :example-rule-options:`http.host; \ - content:"suricata.io";` bsize:11; classtype:bad-unknown; sid:123; rev:1;) +.. _http.cookie: -.. note:: The ``nocase`` keyword is no longer allowed since the host names - are normalized to contain only lowercase letters. +http.cookie +----------- -.. note:: ``http.host`` does not contain the port associated with the host - (i.e. suricata.io:1234). To match on the host and port or negate a host - and port use :ref:`http.host.raw`. +The ``http.cookie`` keyword is used to match on the cookie field that can be +present in HTTP request (Cookie) or HTTP response (Set-Cookie) headers. -.. note:: ``http.host`` does not include the leading space or trailing \\r\\n +It is possible to use any of the :doc:`payload-keywords` with both ``http.header`` +keywords. -.. note:: The ``http.host`` and ``http.host.raw`` buffers are populated - from either the URI (if the full URI is present in the request like - in a proxy request) or the HTTP Host header. If both are present, the - URI is used. +.. note:: Cookies are passed in HTTP headers but Suricata extracts the cookie + data to ``http.cookie`` and will not match cookie content put in the + :ref:`http.header` sticky buffer. -.. note:: If a request contains multiple "Host" headers, the values will be - concatenated in the ``http.host`` and ``http.host.raw`` - buffers, in the order seen from top to bottom, with a comma and space - (", ") between each of them. +.. note:: ``http.cookie`` does not include the leading space or trailing \\r\\n -Example Duplicate Host Header Request:: +Example HTTP Request:: GET /index.html HTTP/1.1 - User-Agent: Chrome/2.0 + User-Agent: Mozilla/5.0 Cookie: PHPSESSION=123 Host: suricata.io - Host: oisf.net .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Two Host Example"; \ - flow:established,to_server; :example-rule-options:`http.host; \ - content:"suricata.io, oisf.net";` classtype:bad-unknown; sid:125; rev:1;) - -.. _http.host.raw: + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Cookie Example"; \ + flow:established,to_server; :example-rule-emphasis:`http.cookie; \ + content:"PHPSESSIONID=123";` bsize:14; classtype:bad-unknown; sid:80; rev:1;) -http.host.raw -------------- +.. _http.header: -The ``http.host.raw`` buffer matches on HTTP host content but does not have -any normalization performed on the buffer contents (see :ref:`http.host`) +http.header +----------- -Example HTTP Request:: +Matching on HTTP headers has two options in Suricata, the ``http.header`` +and the ``http.header.raw``. - GET /index.html HTTP/1.1 - User-Agent: Mozilla/5.0 - Host: SuRiCaTa.Io:8445 +It is possible to use any of the :doc:`payload-keywords` with both +``http.header`` keywords. -.. container:: example-rule +The ``http.header`` keyword normalizes the header contents. For example if +header contents contain trailing white-space or tab characters, those would be +removed. - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Host Raw Example"; \ - flow:established,to_server; :example-rule-options:`http.host.raw; \ - content:"SuRiCaTa.Io|3a|8445";` bsize:16; classtype:bad-unknown; sid:124; rev:1;) +To match on non-normalized header data, use the :ref:`http.header.raw` keyword. -.. note:: ``http.host.raw`` does not include the leading space or trailing \\r\\n +Normalization Example:: -.. note:: The ``http.host`` and ``http.host.raw`` buffers are populated - from either the URI (if the full URI is present in the request like - in a proxy request) or the HTTP Host header. If both are present, the - URI is used. + GET /index.html HTTP/1.1 + User-Agent: Mozilla/5.0 \r\n + Host: suricata.io -.. note:: If a request contains multiple "Host" headers, the values will be - concatenated in the ``http.host`` and ``http.host.raw`` buffers, in the - order seen from top to bottom, with a comma and space (", ") between each - of them. +Would be normalized to :example-rule-emphasis:`Mozilla/5.0\\r\\n` -Example Duplicate Host Header Request:: +Example HTTP Request:: GET /index.html HTTP/1.1 - User-Agent: Chrome/2.0 - Cookie: PHPSESSION=123 + User-Agent: Mozilla/5.0 Host: suricata.io - Host: oisf.net .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Two Host Example"; \ - flow:established,to_server; :example-rule-options:`http.host.raw; \ - content:"suricata.io, oisf.net";` classtype:bad-unknown; sid:125; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Example 1"; \ + flow:established,to_server; :example-rule-options:`http.header; \ + content:"User-Agent|3a 20|Mozilla/5.0|0d 0a|";` classtype:bad-unknown; \ + sid:70; rev:1;) -.. _http.request_header: + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Example 2"; \ + flow:established,to_server; :example-rule-options:`http.header; \ + content:"Host|3a 20|suricata.io|0d 0a|";` classtype:bad-unknown; \ + sid:71; rev:1;) -http.request_header -------------------- + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Example 3"; \ + flow:established,to_server; :example-rule-options:`http.header; \ + content:"User-Agent|3a 20|Mozilla/5.0|0d 0a|"; startswith; \ + content:"Host|3a 20|suricata.io|0d 0a|";` classtype:bad-unknown; \ + sid:72; rev:1;) -The ``http.request_header`` keyword is used to match on the name and value -of a HTTP/1 or HTTP/2 request. +.. note:: There are headers that will not be included in the ``http.header`` + buffer, specifically the :ref:`http.cookie` buffer. -It is possible to use any of the :doc:`payload-keywords` with the -``http.request_header`` keyword. +.. note:: If there are multiple values for the same header name, they are + concatenated with a comma and space (", ") between each value. + More information can be found in RFC 2616 + ``_ -For HTTP/2, the header name and value get concatenated by ": " (colon and space). -The colon and space are commonly noted with the hexadecimal format `|3a 20|` -within signatures. +.. _http.header.raw: -To detect if an HTTP/2 header name contains a ":" (colon), the keyword -:ref:`http2.header_name` can be used. +http.header.raw +--------------- -Example HTTP/1 Request:: +The ``http.header.raw`` buffer matches on HTTP header content but does not have +any normalization performed on the buffer contents (see :ref:`http.header`) + +Abnormal HTTP Header Example:: GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0 + User-Agent: Chrome Host: suricata.io .. container:: example-rule - alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Request Example"; \ - flow:established,to_server; :example-rule-options:`http.request_header; \ - content:"Host|3a 20|suricata.io";` classtype:bad-unknown; sid:126; rev:1;) - -.. note:: ``http.request_header`` does not include the trailing \\r\\n + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Raw Example"; \ + flow:established,to_server; :example-rule-options:`http.header.raw; \ + content:"User-Agent|3a 20|Mozilla/5.0|0d 0a|"; \ + content:"User-Agent|3a 20|Chrome|0d 0a|";` classtype:bad-unknown; sid:73; rev:1;) -.. _http.response_header: +.. _http.header_names: -http.response_header --------------------- +http.header_names +----------------- -The ``http.response_header`` keyword is used to match on the name and value -of an HTTP/1 or HTTP/2 request. +The ``http.header_names`` keyword is used to match on the names of the headers +in an HTTP request or response. This is useful for checking for a header's +presence, absence and/or header order. Use ``flow:to_server`` or +``flow:to_client`` to force inspection of the request or response respectively. It is possible to use any of the :doc:`payload-keywords` with the -``http.response_header`` keyword. +``http.header_names`` keyword. -For HTTP/2, the header name and value get concatenated by ": " (colon and space). -The colon and space are commonly noted with the hexadecimal format `|3a 20|` -within signatures. +Example HTTP Request:: -To detect if an HTTP/2 header name contains a ":" (colon), the keyword -:ref:`http2.header_name` can be used. + GET / HTTP/1.1 + Host: suricata.io + Connection: Keep-Alive Example HTTP Response:: HTTP/1.1 200 OK Content-Type: text/html Server: nginx/0.8.54 - Location: suricata.io + +Examples to match exactly on header order: .. container:: example-rule - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Response Example"; \ - flow:established,to_client; :example-rule-options:`http.response_header; \ - content:"Location|3a 20|suricata.io";` classtype:bad-unknown; sid:127; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ + Example"; flow:established,to_server; :example-rule-options:`http.header_names; \ + content:"|0d 0a|Host|0d 0a|Connection|0d 0a 0d 0a|";` bsize:22; \ + classtype:bad-unknown; sid:110; rev:1;) -.. _file.data: + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Header Names Response \ + Example"; flow:established,to_client; :example-rule-options:`http.header_names; \ + content:"|0d 0a|Content-Type|0d 0a|Server|0d 0a 0d a0|";` bsize:26; \ + classtype:bad-unknown; sid:111; rev:1;) -file.data ---------- +Examples to match on header existence: -With ``file.data``, the HTTP response body is inspected, just like -with ``http.response_body``. ``file.data`` also works for HTTP request -body and can be used in protocols other than HTTP. +.. container:: example-rule -It is possible to use any of the :doc:`payload-keywords` with the -``file.data`` keyword. + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ + Example 2"; flow:established,to_server; :example-rule-options:`http.header_names; \ + content:"|0d 0a|Host|0d 0a|";` classtype:bad-unknown; sid:112; rev:1;) -Example HTTP Response:: + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Header Names Response \ + Example 2"; flow:established,to_client; :example-rule-options:`http.header_names; \ + content:"|0d 0a|Content-Type|0d 0a|";` classtype:bad-unknown; sid:113; rev:1;) - HTTP/1.1 200 OK - Content-Type: text/html - Server: nginx/0.8.54 +Examples to match on header absence: - Server response body +.. container:: example-rule + + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ + Example 3"; flow:established,to_server; :example-rule-options:`http.header_names; \ + content:!"|0d 0a|User-Agent|0d 0a|";` classtype:bad-unknown; sid:114; rev:1;) + + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Header Names Response \ + Example 3"; flow:established,to_client; :example-rule-options:`http.header_names; \ + content:!"|0d 0a|Date|0d 0a|";` classtype:bad-unknown; sid:115; rev:1;) + +Example to check for the ``User-Agent`` header and that the ``Host`` header is +after ``User-Agent`` but not necessarily directly after. .. container:: example-rule - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP file.data Example"; \ - flow:established,to_client; :example-rule-options:`file.data; \ - content:"Server response body";` classtype:bad-unknown; sid:128; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Header Names Request \ + Example 4"; flow:established,to_server; :example-rule-options:`http.header_names; \ + content:"|0d 0a|Host|0d 0a|";` content:"User-Agent|0d 0a|"; distance:-2; \ + classtype:bad-unknown; sid:114; rev:1;) -The body of an HTTP response can be very large, therefore the response body is -inspected in definable chunks. +.. note:: ``http.header_names`` starts with a \\r\\n and ends with an extra \\r\\n. -How much of the response/server body is inspected is controlled -in the :ref:`libhtp configuration section -` via the ``response-body-limit`` -setting. +.. _http.protocol: -.. note:: If the HTTP body is a flash file compressed with 'deflate' or 'lzma', - it can be decompressed and ``file.data`` can match on the decompressed data. - Flash decompression must be enabled under 'libhtp' configuration: +http.protocol +------------- - :: +The ``http.protocol`` keyword is used to match on the protocol field that is +contained in HTTP requests and responses. - # Decompress SWF files. - # 2 types: 'deflate', 'lzma', 'both' will decompress deflate and lzma - # compress-depth: - # Specifies the maximum amount of data to decompress, - # set 0 for unlimited. - # decompress-depth: - # Specifies the maximum amount of decompressed data to obtain, - # set 0 for unlimited. - swf-decompression: - enabled: yes - type: both - compress-depth: 0 - decompress-depth: 0 +It is possible to use any of the :doc:`payload-keywords` with the +``http.protocol`` keyword. -.. note:: ``file.data`` replaces the previous keyword name, ``file_data``. - ``file_data`` can still be used but it is recommended that rules be converted - to use ``file.data``. +.. note:: ``http.protocol`` does not include the leading space or trailing \\r\\n -.. note:: If an HTTP body is using gzip or deflate, ``file.data`` will match on - the decompressed data. +Example HTTP Request:: -.. note:: Negated matching is affected by the chunked inspection. E.g. - 'content:!" $EXTERNAL_NET any (msg:"HTTP Protocol Example"; \ + flow:established,to_server; :example-rule-options:`http.protocol; \ + content:"HTTP/1.1";` bsize:9; classtype:bad-unknown; sid:50; rev:1;) -.. _file.name: +.. _http.start: -file.name ---------- +http.start +---------- -The ``file.name`` keyword can be used with HTTP requests. +The ``http.start`` keyword is used to match on the start of an HTTP request +or response. This will contain the request/response line plus the request/response +headers. Use ``flow:to_server`` or ``flow:to_client`` to force inspection of the +request or response respectively. It is possible to use any of the :doc:`payload-keywords` with the -``file.name`` keyword. +``http.start`` keyword. Example HTTP Request:: - GET /picture.jpg HTTP/1.1 - User-Agent: Mozilla/5.0 + GET / HTTP/1.1 Host: suricata.io + Connection: Keep-Alive + +Example HTTP Response:: + + HTTP/1.1 200 OK + Content-Type: text/html + Server: nginx/0.8.54 .. container:: example-rule - alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP file.name Example"; \ - flow:established,to_client; :example-rule-options:`file.name; \ - content:"picture.jpg";` classtype:bad-unknown; sid:129; rev:1;) + alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"HTTP Start Request \ + Example"; flow:established,to_server; :example-rule-options:`http.start; \ + content:"POST / HTTP/1.1|0d 0a|Host|0d 0a|Connection|0d 0a 0d 0a|";` \ + classtype:bad-unknown; sid:101; rev:1;) -.. note:: Additional information can be found at :doc:`file-keywords` \ No newline at end of file + alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"HTTP Start Response \ + Example"; flow:established,to_client; :example-rule-options:`http.start; \ + content:"HTTP/1.1 200 OK|0d 0a|Content-Type|0d 0a|Server|0d 0a 0d a0|";` \ + classtype:bad-unknown; sid:102; rev:1;) + +.. note:: ``http.start`` contains the normalized headers and is terminated by + an extra \\r\\n to indicate the end of the headers. \ No newline at end of file