]>
Commit | Line | Data |
---|---|---|
0af562d4 VJ |
1 | ====================== |
2 | Differences From Snort | |
3 | ====================== | |
6bc7c647 | 4 | |
6bc7c647 DW |
5 | This document is intended to highlight the major differences between Suricata |
6 | and Snort that apply to rules and rule writing. | |
7 | ||
8 | Where not specified, the statements below apply to Suricata. In general, | |
9 | references to Snort refer to the version 2.9 branch. | |
10 | ||
6bc7c647 DW |
11 | Automatic Protocol Detection |
12 | ---------------------------- | |
13 | ||
14 | - Suricata does automatic protocol detection of the following | |
15 | application layer protocols: | |
16 | ||
17 | - dcerpc | |
0af562d4 | 18 | - dnp3 |
6bc7c647 DW |
19 | - dns |
20 | - http | |
21 | - imap (detection only by default; no parsing) | |
22 | - ftp | |
23 | - modbus (disabled by default; minimalist probe parser; can lead to false positives) | |
6bc7c647 DW |
24 | - smb |
25 | - smb2 (disabled internally inside the engine) | |
26 | - smtp | |
27 | - ssh | |
0af562d4 | 28 | - tls (SSLv2, SSLv3, TLSv1, TLSv1.1 and TLSv1.2) |
6bc7c647 DW |
29 | |
30 | - In Suricata, protocol detection is port agnostic (in most cases). In | |
31 | Snort, in order for the ``http_inspect`` and other preprocessors to be | |
32 | applied to traffic, it has to be over a configured port. | |
33 | ||
34 | - Some configurations for app-layer in the Suricata yaml can/do by default | |
35 | specify specific destination ports (e.g. DNS) | |
36 | - **You can look on 'any' port without worrying about the | |
37 | performance impact that you would have to be concerned about with | |
38 | Snort.** | |
39 | ||
40 | - If the traffic is detected as HTTP by Suricata, the ``http_*`` | |
41 | buffers are populated and can be used, regardless of port(s) | |
42 | specified in the rule. | |
43 | ||
44 | - You don't have to check for the http protocol (i.e. | |
45 | ``alert http ...``) to use the ``http_*`` buffers although it | |
46 | is recommended. | |
47 | ||
48 | - If you are trying to detect legitimate (supported) application layer | |
49 | protocol traffic and don't want to look on specific port(s), the rule | |
50 | should be written as ``alert <protocol> ...`` with ``any`` in | |
51 | place of the usual protocol port(s). For example, when you want to | |
52 | detect HTTP traffic and don't want to limit detection to a particular | |
53 | port or list of ports, the rules should be written as | |
54 | ``alert http ...`` with ``any`` in place of | |
55 | ``$HTTP_PORTS``. | |
56 | ||
57 | - You can also use ``app-layer-protocol:<protocol>;`` inside the rule instead. | |
58 | ||
59 | So, instead of this Snort rule:: | |
60 | ||
61 | alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS ... | |
62 | ||
63 | Do this for Suricata:: | |
64 | ||
65 | alert http $HOME_NET -> $EXTERNAL_NET any ... | |
66 | ||
67 | Or:: | |
68 | ||
69 | alert tcp $HOME_NET any -> $EXTERNAL_NET any (app-layer-protocol:http; ... | |
70 | ||
71 | ``urilen`` Keyword | |
72 | ------------------ | |
73 | ||
74 | - Ranges given in the ``urilen`` keyword are inclusive for Snort | |
75 | but not inclusive for Suricata. | |
76 | ||
77 | Example: ``urilen:2<>10`` | |
78 | ||
79 | - Snort interprets this as, "the URI length must be **greater than | |
80 | or equal to** 2, and **less than or equal to** 10". | |
81 | - Suricata interprets this as "the URI length must be **greater | |
82 | than** 2 and **less than** 10". | |
83 | ||
84 | - There is a request to have Suricata behave like Snort in future | |
85 | versions – | |
86 | `https://redmine.openinfosecfoundation.org/issues/1416 <https://redmine.openinfosecfoundation.org/issues/1416>`_ | |
87 | ||
88 | - Currently on hold | |
89 | ||
90 | - By default, with *Suricata*, ``urilen`` applies to the | |
91 | **normalized** buffer | |
92 | ||
93 | - Use ``,raw`` for raw buffer | |
94 | - e.g. ``urilen:>20,raw;`` | |
95 | ||
96 | - By default, with *Snort*, ``urilen`` applies to the **raw** | |
97 | buffer | |
98 | ||
99 | - Use ``,norm`` for normalized buffer | |
100 | - e.g. ``urilen:>20,norm;`` | |
101 | ||
102 | ``http_uri`` Buffer | |
103 | ------------------- | |
104 | ||
105 | - In Snort, the ``http_uri`` buffer normalizes '+' characters | |
106 | (0x2B) to spaces (0x20). | |
107 | ||
108 | - Suricata can do this as well but you have to explicitly | |
109 | set ``query-plusspace-decode: yes`` in the ``libhtp`` section of Suricata's yaml file. | |
110 | ||
111 | - `https://redmine.openinfosecfoundation.org/issues/1035 <https://redmine.openinfosecfoundation.org/issues/1035>`_ | |
112 | - `https://github.com/inliniac/suricata/pull/620 <https://github.com/inliniac/suricata/pull/620>`_ | |
113 | ||
114 | ``http_header`` Buffer | |
115 | ---------------------- | |
116 | ||
117 | - In Snort, the ``http_header`` buffer includes the CRLF CRLF (0x0D | |
118 | 0x0A 0x0D 0x0A) that separates the end of the last HTTP header from | |
119 | the beginning of the HTTP body. Suricata includes a CRLF after the | |
120 | last header in the ``http_header`` buffer but not an extra one | |
121 | like Snort does. If you want to match the end of the buffer, use | |
122 | either the ``http_raw_header`` buffer, a relative | |
123 | ``isdataat`` (e.g. ``isdataat:!1,relative``) or a PCRE | |
124 | (although PCRE will be worse on performance). | |
125 | ||
126 | - Suricata *will* include CRLF CRLF at the end of the ``http_raw_header`` | |
127 | buffer like Snort does. | |
128 | ||
129 | - Snort will include a *leading* CRLF in the ``http_header`` buffer of | |
130 | *server responses* (but not client requests). Suricata does not have | |
131 | the leading CRLF in the ``http_header`` buffer of the server response | |
132 | or client request. | |
133 | ||
134 | - In the ``http_header`` buffer, Suricata will normalize HTTP header lines | |
135 | such that there is a single space (0x20) after the colon (':') that | |
136 | separates the header name from the header value; this single space | |
137 | replaces zero or more whitespace characters (including tabs) that may be | |
138 | present in the raw HTTP header line immediately after the colon. If the | |
139 | extra whitespace (or lack thereof) is important for matching, use | |
140 | the ``http_raw_header`` buffer instead of the ``http_header`` buffer. | |
141 | ||
142 | - Snort will also normalize superfluous whitespace between the header name | |
143 | and header value like Suricata does but only if there is at least one space | |
144 | character (0x20 only so not 0x90) immediately after the colon. This means | |
145 | that, unlike Suricata, if there is no space (or if there is a tab) | |
146 | immediately after the colon before the header value, the content of the | |
147 | header line will remain unchanged in the ``http_header`` buffer. | |
148 | ||
149 | - When there are duplicate HTTP headers (referring to the header name | |
150 | only, not the value), the normalized buffer (``http_header``) | |
151 | will concatenate the values in the order seen (from top to | |
152 | bottom), with a comma and space (", ") between each of them. If this | |
153 | hinders detection, use the ``http_raw_header`` buffer instead. | |
154 | ||
155 | Example request:: | |
156 | ||
157 | GET /test.html HTTP/1.1 | |
158 | Content-Length: 44 | |
159 | Accept: */* | |
160 | Content-Length: 55 | |
161 | ||
162 | The Content-Length header line becomes this in the ``http_header`` buffer:: | |
163 | ||
164 | Content-Length: 44, 55 | |
165 | ||
166 | - The HTTP 'Cookie' and 'Set-Cookie' headers are **NOT** included in | |
167 | the ``http_header`` buffer; instead they are extracted and put into | |
168 | their own buffer – ``http_cookie``. See the `http_cookie Buffer`_ | |
169 | section. | |
170 | ||
171 | - The HTTP 'Cookie' and 'Set-Cookie' headers **ARE** included in the | |
172 | ``http_raw_header`` buffer so if you are trying to match on | |
173 | something like particular header ordering involving (or not | |
174 | involving) the HTTP Cookie headers, use the ``http_raw_header`` | |
175 | buffer. | |
176 | ||
177 | - If 'enable\_cookie' is set for Snort, the HTTP Cookie header names | |
178 | and trailing CRLF (i.e. "Cookie: \\r\\n" and "Set-Cooke \\r\\n") are | |
179 | kept in the ``http_header`` buffer. This is not the case for | |
180 | Suricata which removes the entire "Cookie" or "Set-Cookie" line from | |
181 | the ``http_header`` buffer. | |
182 | ||
183 | - Other HTTP headers that have their own buffer | |
184 | (``http_user_agent``, ``http_host``) are not removed from the | |
185 | ``http_header`` buffer like the Cookie headers are. | |
186 | ||
187 | - When inspecting server responses and ``file_data`` is used, | |
188 | content matches in ``http_*`` buffers should come before | |
189 | ``file_data`` unless you use ``pkt_data`` to reset the cursor | |
190 | before matching in ``http_*`` buffers. Snort will not complain if | |
191 | you use ``http_*`` buffers after ``file_data`` is set. | |
192 | ||
193 | ``http_cookie`` Buffer | |
194 | ---------------------- | |
195 | ||
196 | - The ``http_cookie`` buffer will NOT include the header name, | |
197 | colon, or leading whitespace. i.e. it will not include "Cookie: " or "Set-Cookie: ". | |
198 | ||
199 | - The ``http_cookie`` buffer does not include a CRLF (0x0D 0x0A) at | |
200 | the end. If you want to match the end of the buffer, use a relative | |
201 | ``isdataat`` or a PCRE (although PCRE will be worse on | |
202 | performance). | |
203 | ||
204 | - There is no ``http_raw_cookie`` buffer in Suricata. Use | |
205 | ``http_raw_header`` instead. | |
206 | ||
207 | - You do not have to configure anything special to use the | |
208 | 'http\_cookie' buffer in Suricata. This is different from Snort | |
209 | where you have to set ``enable_cookie`` in the | |
210 | ``http_inspect_server`` preprocessor config in order to have the | |
211 | ``http_cookie`` buffer treated separate from the | |
212 | ``http_header`` buffer. | |
213 | ||
214 | - If Snort has 'enable\_cookie' set and multiple "Cookie" or | |
215 | "Set-Cookie" headers are seen, it will concatenate them together | |
216 | (with no separator between them) in the order seen from top to | |
217 | bottom. | |
218 | ||
219 | - If a request contains multiple "Cookie" or "Set-Cookie" headers, the | |
220 | values will be concatenated in the Suricata ``http_cookie`` | |
221 | buffer, in the order seen from top to bottom, with a comma and space | |
222 | (", ") between each of them. | |
223 | ||
224 | Example request:: | |
225 | ||
226 | GET /test.html HTTP/1.1 | |
227 | Cookie: monster | |
228 | Accept: */* | |
229 | Cookie: elmo | |
230 | ||
231 | Suricata ``http_cookie`` buffer contents:: | |
232 | ||
233 | monster, elmo | |
234 | ||
235 | Snort ``http_cookie`` buffer contents:: | |
236 | ||
237 | monsterelmo | |
238 | ||
239 | - Corresponding PCRE modifier: ``C`` (same as Snort) | |
240 | ||
0af562d4 VJ |
241 | New HTTP keywords |
242 | ----------------- | |
6bc7c647 | 243 | |
0af562d4 | 244 | Suricata supports several HTTP keywords that Snort doesn't have. |
6bc7c647 | 245 | |
0af562d4 | 246 | Examples are ``http_user_agent``, ``http_host`` and ``http_content_type``. |
6bc7c647 | 247 | |
0af562d4 | 248 | See :doc:`http-keywords` for all HTTP keywords. |
6bc7c647 | 249 | |
6bc7c647 DW |
250 | |
251 | ``byte_extract`` Keyword | |
252 | ------------------------ | |
253 | ||
254 | - Suricata supports | |
255 | ``byte_extract`` from ``http_*`` buffers, including | |
256 | ``http_header`` which does not always work as expected in Snort. | |
257 | ||
258 | - In Suricata, variables extracted using ``byte_extract`` must be used | |
259 | in the same buffer, otherwise they will have the value "0" (zero). Snort | |
260 | does allow cross-buffer byte extraction and usage. | |
261 | ||
262 | - Be sure to always positively and negatively test Suricata rules that | |
263 | use ``byte_extract`` and ``byte_test`` to verify that they | |
264 | work as expected. | |
265 | ||
266 | ``isdataat`` Keyword | |
267 | -------------------- | |
268 | ||
269 | - The ``rawbytes`` keyword is supported in the Suricata syntax but | |
270 | doesn't actually do anything. | |
271 | ||
272 | - Absolute ``isdataat`` checks will succeed if the offset used is | |
273 | **less than** the size of the inspection buffer. This is true for | |
274 | Suricata and Snort. | |
275 | ||
276 | - For *relative* ``isdataat`` checks, there is a **1 byte difference** | |
277 | in the way Snort and Suricata do the comparisons. | |
278 | ||
279 | - Suricata will succeed if the relative offset is **less than or | |
280 | equal to** the size of the inspection buffer. This is different | |
281 | from absolute ``isdataat`` checks. | |
282 | - Snort will succeed if the relative offset is **less than** the | |
283 | size of the inspection buffer, just like absolute ``isdataat`` | |
284 | checks. | |
285 | - Example - to check that there is no data in the inspection buffer | |
286 | after the last content match: | |
287 | ||
288 | - Snort: ``isdataat:!0,relative;`` | |
289 | - Suricata: ``isdataat:!1,relative;`` | |
290 | ||
291 | - With Snort, the "inspection buffer" used when checking an | |
292 | ``isdataat`` keyword is generally the packet/segment with some | |
293 | exceptions: | |
294 | ||
295 | - With PAF enabled the PDU is examined instead of the | |
296 | packet/segment. When ``file_data`` or ``base64_data`` has | |
297 | been set, it is those buffers (unless ``rawbytes`` is set). | |
298 | - With some preprocessors - modbus, gtp, sip, dce2, and dnp3 - the | |
299 | buffer can be particular portions of those protocols (unless | |
300 | ``rawbytes`` is set). | |
301 | - With some preprocessors - rpc\_decode, ftp\_telnet, smtp, and dnp3 | |
302 | - the buffer can be particular *decoded* portions of those | |
303 | protocols (unless ``rawbytes`` is set). | |
304 | ||
305 | - With Suricata, the "inspection buffer" used when checking an absolute | |
306 | ``isdataat`` keyword is the packet/segment if looking at a packet | |
307 | (e.g. ``alert tcp-pkt...``) or the reassembled stream segments. | |
308 | ||
309 | - In Suricata, a *relative* ``isdataat`` keyword **will apply to the | |
310 | buffer of the previous content match**. So if the previous content | |
311 | match is a ``http_*`` buffer, the relative ``isdataat`` | |
312 | applies to that buffer, starting from the end of the previous content | |
313 | match in that buffer. *Snort does not behave like this!* | |
314 | ||
315 | - For example, this Suricata rule looks for the string ".exe" at the | |
316 | end of the URI; to do the same thing in the normalized URI buffer in | |
317 | Snort you would have to use a PCRE – ``pcre:"/\x2Eexe$/U";`` | |
318 | ||
319 | :: | |
320 | ||
321 | alert http $HOME_NET any -> $EXTERNAL_NET any (msg:".EXE File Download Request"; flow:established,to_server; content:"GET"; http_method; content:".exe"; http_uri; isdataat:!1,relative; priority:3; sid:18332111;) | |
322 | ||
323 | - If you are unclear about behavior in a particular instance, you are | |
324 | encouraged to positively and negatively test your rules that use an | |
325 | ``isdataat`` keyword. | |
326 | ||
327 | Relative PCRE | |
328 | ------------- | |
329 | ||
330 | - You can do relative PCRE matches in normalized/special buffers with Suricata. Example:: | |
331 | ||
332 | content:".php?sign="; http_uri; pcre:"/^[a-zA-Z0-9]{8}$/UR"; | |
333 | ||
30fd80b0 | 334 | - With Snort you can't combine the "relative" PCRE option ('R') with other buffer options like normalized URI ('U') – you get a syntax error. |
6bc7c647 DW |
335 | |
336 | ``tls*`` Keywords | |
337 | ------------------ | |
338 | ||
339 | In addition to TLS protocol identification, Suricata supports the storing of | |
340 | certificates to disk, verifying the validity dates on certificates, matching | |
341 | against the calculated SHA1 fingerprint of certificates, and | |
342 | matching on certain TLS/SSL certificate fields including the following: | |
343 | ||
344 | - Negotiated TLS/SSL version. | |
345 | - Certificate Subject field. | |
346 | - Certificate Issuer field. | |
347 | - Certificate SNI Field | |
348 | ||
349 | For details see :doc:`tls-keywords`. | |
350 | ||
351 | ``dns_query`` Keyword | |
352 | --------------------- | |
353 | ||
354 | - Sets the detection pointer to the DNS query. | |
355 | ||
356 | - Works like ``file_data`` does ("sticky buffer") but for a DNS | |
357 | request query. | |
358 | ||
359 | - Use ``pkt_data`` to reset the detection pointer to the beginning of | |
360 | the packet payload. | |
361 | ||
0af562d4 | 362 | - See :doc:`dns-keywords` for details. |
6bc7c647 DW |
363 | |
364 | IP Reputation and ``iprep`` Keyword | |
365 | ----------------------------------- | |
366 | ||
367 | - Snort has the "reputation" preprocessor that can be used to define | |
368 | whitelist and blacklist files of IPs which are used generate GID 136 | |
369 | alerts as well as block/drop/pass traffic from listed IPs depending | |
370 | on how it is configured. | |
371 | ||
372 | - Suricata also has the concept of files with IPs in them but provides | |
373 | the ability to assign them: | |
374 | ||
375 | - Categories | |
376 | - Reputation score | |
377 | ||
378 | - Suricata rules can leverage these IP lists with the ``iprep`` | |
379 | keyword that can be configured to match on: | |
380 | ||
381 | - Direction | |
382 | - Category | |
383 | - Value (reputation score) | |
384 | ||
385 | - :doc:`../reputation/index` | |
386 | - :doc:`../reputation/ipreputation/ip-reputation-config` | |
98a1ec49 | 387 | - :doc:`ip-reputation-rules` |
6bc7c647 | 388 | - :doc:`../reputation/ipreputation/ip-reputation-format` |
2e8678a5 | 389 | - `https://blog.inliniac.net/2012/11/21/ip-reputation-in-suricata/ <https://blog.inliniac.net/2012/11/21/ip-reputation-in-suricata/>`_ |
6bc7c647 | 390 | |
6bc7c647 DW |
391 | Flowbits |
392 | -------- | |
393 | ||
394 | - Suricata fully supports the setting and checking of flowbits | |
395 | (including the same flowbit) on the same packet/stream. Snort does | |
396 | not always allow for this. | |
397 | ||
398 | - In Suricata, ``flowbits:isset`` is checked after the fast pattern | |
399 | match but before other ``content`` matches. In Snort, | |
400 | ``flowbits:isset`` is checked in the order it appears in the | |
401 | rule, from left to right. | |
402 | ||
403 | - If there is a chain of flowbits where multiple rules set flowbits and | |
404 | they are dependent on each other, then the order of the rules or the | |
405 | ``sid`` values can make a | |
406 | difference in the rules being evaluated in the proper order and | |
407 | generating alerts as expected. See bug 1399 - | |
408 | `https://redmine.openinfosecfoundation.org/issues/1399 <https://redmine.openinfosecfoundation.org/issues/1399>`_. | |
409 | ||
410 | - :doc:`flow-keywords` | |
411 | ||
0af562d4 VJ |
412 | flowbits:noalert; |
413 | ----------------- | |
414 | ||
415 | A common pattern in existing rules is to use ``flowbits:noalert;`` to make | |
416 | sure a rule doesn't generate an alert if it matches. | |
417 | ||
418 | Suricata allows using just ``noalert;`` as well. Both have an identical meaning | |
419 | in Suricata. | |
420 | ||
6bc7c647 DW |
421 | Negated Content Match Special Case |
422 | ---------------------------------- | |
423 | ||
424 | - For Snort, a *negated* content match where the starting point for | |
425 | searching is at or beyond the end of the inspection buffer will never | |
426 | return true. | |
427 | ||
428 | - For negated matches, you want it to return true if the content is | |
429 | not found. | |
430 | - This is believed to be a Snort bug rather than an engine difference | |
431 | but it was reported to Sourcefire and acknowledged many years ago | |
432 | indicating that perhaps it is by design. | |
433 | - This is not the case for Suricata which behaves as | |
434 | expected. | |
435 | ||
436 | Example HTTP request:: | |
437 | ||
438 | POST /test.php HTTP/1.1 | |
439 | Content-Length: 9 | |
440 | ||
441 | user=suri | |
442 | ||
443 | This rule snippet will never return true in Snort but will in | |
444 | Suricata:: | |
445 | ||
446 | content:!"snort"; offset:10; http_client_body; | |
447 | ||
448 | File Extraction | |
449 | --------------- | |
450 | ||
0ff60f65 | 451 | - Suricata has the ability to match on files from FTP, HTTP and SMTP streams and |
6bc7c647 DW |
452 | log them to disk. |
453 | ||
454 | - Snort has the "file" preprocessor that can do something similar | |
455 | but it is experimental, development of it | |
456 | has been stagnant for years, and it is not something that should be used | |
457 | in a production environment. | |
458 | ||
459 | - Files can be matched on using a number of keywords including: | |
460 | ||
461 | - ``filename`` | |
462 | - ``fileext`` | |
463 | - ``filemagic`` | |
464 | - ``filesize`` | |
465 | - ``filemd5`` | |
466 | - ``filesha1`` | |
467 | - ``filesha256`` | |
468 | - ``filesize`` | |
469 | - See :doc:`file-keywords` for a full list. | |
470 | ||
471 | - The ``filestore`` keyword tells Suricata to save the file to | |
472 | disk. | |
473 | ||
474 | - Extracted files are logged to disk with meta data that includes | |
475 | things like timestamp, src/dst IP, protocol, src/dst port, HTTP URI, | |
476 | HTTP Host, HTTP Referer, filename, file magic, md5sum, size, etc. | |
477 | ||
478 | - There are a number of configuration options and considerations (such | |
479 | as stream reassembly depth and libhtp body-limit) that should be | |
480 | understood if you want fully utilize file extraction in Suricata. | |
481 | ||
482 | - :doc:`file-keywords` | |
483 | - :doc:`../file-extraction/file-extraction` | |
2e8678a5 AH |
484 | - `https://blog.inliniac.net/2011/11/29/file-extraction-in-suricata/ <https://blog.inliniac.net/2011/11/29/file-extraction-in-suricata/>`_ |
485 | - `https://blog.inliniac.net/2014/11/11/smtp-file-extraction-in-suricata/ <https://blog.inliniac.net/2014/11/11/smtp-file-extraction-in-suricata/>`_ | |
6bc7c647 DW |
486 | |
487 | Lua Scripting | |
488 | ------------- | |
489 | ||
0af562d4 VJ |
490 | - Suricata has the ``lua`` (or ``luajit``) keyword which allows for a |
491 | rule to reference a Lua script that can access the packet, payload, | |
492 | HTTP buffers, etc. | |
6bc7c647 DW |
493 | - Provides powerful flexibility and capabilities that Snort does |
494 | not have. | |
4256c1cc | 495 | - More details in: :ref:`lua-detection` |
6bc7c647 DW |
496 | |
497 | Fast Pattern | |
498 | ------------ | |
499 | ||
500 | - Snort's fast pattern matcher is always case insensitive; Suricata's | |
501 | is case sensitive unless 'nocase' is set on the content match used by | |
502 | the fast pattern matcher. | |
503 | ||
504 | - Snort will truncate fast pattern matches based on the | |
505 | ``max-pattern-len`` config (default no limit) unless | |
506 | ``fast_pattern:only`` is used in the rule. Suricata does not do any | |
507 | automatic fast pattern truncation cannot be configured to do so. | |
508 | ||
509 | - Just like in Snort, in Suricata you can specify a substring of the | |
510 | content string to be use as the fast pattern match. e.g. | |
511 | ``fast_pattern:5,20;`` | |
512 | ||
513 | - In Snort, leading NULL bytes (0x00) will be removed from content | |
514 | matches when determining/using the longest content match unless | |
515 | ``fast_pattern`` is explicitly set. Suricata does not truncate | |
516 | anything, including NULL bytes. | |
517 | ||
518 | - Snort does not allow for all ``http_*`` buffers to be used for | |
519 | the fast pattern match (e.g. ``http_raw_*``, ``http_method``, | |
520 | ``http_cookie``, etc.). Suricata lets you use any 'http\_\*' | |
521 | buffer you want for the fast pattern match, including | |
522 | ``http_raw_*' and ``http_cookie`` buffers. | |
523 | ||
524 | - Suricata supports the ``fast_pattern:only`` syntax but | |
525 | technically it is not really implemented; the ``only`` is | |
526 | silently ignored when encountered in a rule. It is still recommended | |
527 | that you use ``fast_pattern:only`` where appropriate in case this | |
528 | gets implemented in the future and/or if the rule will be used by | |
529 | Snort as well. | |
530 | ||
531 | - With Snort, unless ``fast_pattern`` is explicitly set, content | |
532 | matches in normalized HTTP Inspect buffers (e.g. http content | |
533 | modifiers such ``http_uri``, ``http_header``, etc.) take | |
534 | precedence over non-HTTP Inspect content matches, even if they are | |
535 | shorter. Suricata does the same thing and gives a higher 'priority' | |
536 | (precedence) to ``http_*`` buffers (except for ``http_method``, | |
537 | ``http_stat_code``, and ``http_stat_msg``). | |
538 | ||
539 | - See :doc:`fast-pattern-explained` for full details on how Suricata | |
540 | automatically determines which content to use as the fast pattern match. | |
541 | ||
542 | - When in doubt about what is going to be use as the fast pattern match | |
543 | by Suricata, set ``fast_pattern`` explicitly in the rule and/or | |
544 | run Suricata with the ``--engine-analysis`` switch and view the | |
545 | generated file (``rules_fast_pattern.txt``). | |
546 | ||
547 | - Like Snort, the fast pattern match is checked before ``flowbits`` | |
548 | in Suricata. | |
549 | ||
550 | - Using Hyperscan as the MPM matcher (``mpm-algo`` setting) for Suricata | |
551 | can greatly improve performance, especially when it comes to fast pattern | |
552 | matching. Hyperscan will also take in to account depth and offset | |
b116a56a | 553 | when doing fast pattern matching, something the other algorithms and |
6bc7c647 DW |
554 | Snort do not do. |
555 | ||
bb1bf264 | 556 | - :ref:`rules-keyword-fast_pattern` |
6bc7c647 DW |
557 | |
558 | Don't Cross The Streams | |
559 | ----------------------- | |
560 | ||
561 | Suricata will examine network traffic as individual packets and, in the | |
562 | case of TCP, as part of a (reassembled) stream. However, there are | |
563 | certain rule keywords that only apply to packets only (``dsize``, | |
564 | ``flags``, ``ttl``) and certain ones that only apply to streams | |
565 | only (``http_*``) and you can't mix packet and stream keywords. Rules | |
566 | that use packet keywords will inspect individual packets only and | |
567 | rules that use stream keywords will inspect streams only. Snort is a | |
568 | little more forgiving when you mix these – for example, in Snort you can | |
569 | use ``dsize`` (a packet keyword) with ``http_*`` (stream | |
570 | keywords) and Snort will allow it although, because of ``dsize``, it | |
571 | will only apply detection to individual packets (unless PAF is enabled | |
572 | then it will apply it to the PDU). | |
573 | ||
574 | If ``dsize`` is in a rule that also looks for a stream-based | |
575 | application layer protocol (e.g. ``http``), Suricata will not match on | |
576 | the *first application layer packet* since ``dsize`` make Suricata | |
577 | evaluate the packet and protocol detection doesn't happen until after | |
578 | the protocol is checked for that packet; *subsequent* packets in that | |
579 | flow should have the application protocol set appropriately and will | |
580 | match rules using ``dsize`` and a stream-based application layer | |
581 | protocol. | |
582 | ||
583 | If you need to check sizes on a stream in a rule that uses a stream | |
584 | keyword, or in a rule looking for a stream-based application layer | |
585 | protocol, consider using the ``stream_size`` keyword and/or | |
586 | ``isdataat``. | |
587 | ||
588 | Suricata also supports these protocol values being used in rules and | |
589 | Snort does not: | |
590 | ||
591 | - ``tcp-pkt`` – example: | |
592 | ||
593 | - ``alert tcp-pkt ...`` | |
594 | - This tells Suricata to only apply the rule to TCP packets and not | |
595 | the (reassembled) stream. | |
596 | ||
597 | - ``tcp-stream`` – example: | |
598 | ||
599 | - ``alert tcp-stream ...`` | |
600 | - This tells Suricata to inspect the (reassembled) TCP stream only. | |
601 | ||
602 | Alerts | |
603 | ------ | |
604 | ||
605 | - In Snort, the number of alerts generated for a packet/stream can be | |
606 | limited by the ``event_queue`` configuration. | |
607 | ||
608 | - Suricata has an internal hard-coded limit of 15 alerts per packet/stream (and | |
609 | this cannot be configured); all rules that match on the traffic being | |
610 | analyzed will fire up to that limit. | |
611 | ||
612 | - Sometimes Suricata will generate what appears to be two alerts for | |
613 | the same TCP packet. This happens when Suricata evaluates the packet | |
614 | by itself and as part of a (reassembled) stream. | |
615 | ||
616 | Buffer Reference Chart | |
617 | ---------------------- | |
618 | ||
619 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
620 | | Buffer | Snort 2.9.x | Suricata | PCRE | Can be used as | Suricata Fast | | |
621 | | | Support? | Support? | flag | Fast Pattern? | Pattern Priority | | |
622 | | | | | | | (lower number is | | |
623 | | | | | | | higher priority) | | |
624 | +=======================+==========================================+===========================================+========+================+==================+ | |
625 | | content (no modifier) | YES | YES | <none> | YES | 3 | | |
626 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
627 | | http_method | YES | YES | M | Suricata only | 3 | | |
628 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
629 | | http_stat_code | YES | YES | S | Suricata only | 3 | | |
630 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
631 | | http_stat_msg | YES | YES | Y | Suricata only | 3 | | |
632 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
633 | | uricontent | YES but deprecated, use http_uri instead | YES but deprecated, use http_uri instead | U | YES | 2 | | |
634 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
635 | | http_uri | YES | YES | U | YES | 2 | | |
636 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
637 | | http_raw_uri | YES | YES | I | Suricata only | 2 | | |
638 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
639 | | http_header | YES | YES | H | YES | 2 | | |
640 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
641 | | http_raw_header | YES | YES | D | Suricata only | 2 | | |
642 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
643 | | http_cookie | YES | YES | C | Suricata only | 2 | | |
644 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
645 | | http_raw_cookie | YES | NO (use http_raw_header instead) | K | NO | n/a | | |
646 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
647 | | http_host | NO | YES | W | Suricata only | 2 | | |
648 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
649 | | http_raw_host | NO | YES | Z | Suricata only | 2 | | |
650 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
651 | | http_client_body | YES | YES | P | YES | 2 | | |
652 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
653 | | http_server_body | NO | YES | Q | Suricata only | 2 | | |
654 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
655 | | http_user_agent | NO | YES | V | Suricata only | 2 | | |
656 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
657 | | dns_query | NO | YES | n/a\* | Suricata only | 2 | | |
658 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
659 | | tls_sni | NO | YES | n/a\* | Suricata only | 2 | | |
660 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
661 | | tls_cert_issuer | NO | YES | n/a\* | Suricata only | 2 | | |
662 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
663 | | tls_cert_subject | NO | YES | n/a\* | Suricata only | 2 | | |
664 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
665 | | file_data | YES | YES | n/a\* | YES | 2 | | |
666 | +-----------------------+------------------------------------------+-------------------------------------------+--------+----------------+------------------+ | |
667 | ||
668 | \* Sticky buffer |