From a5eeb47268001987e1457bc9f62caf050857a0da Mon Sep 17 00:00:00 2001 From: Jeff Lucovsky Date: Wed, 3 Jul 2024 08:30:44 -0400 Subject: [PATCH 1/2] decode/ethertype: Event on unknown ethertype Issue: 7129 Create a decode/engine event if unknown ethertypes are observed. --- etc/schema.json | 3 +++ rules/decoder-events.rules | 3 ++- src/decode-events.c | 4 ++++ src/decode-events.h | 3 ++- src/decode.c | 3 +++ src/decode.h | 11 +++++++++-- 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/etc/schema.json b/etc/schema.json index 74439841a22f..c1eeff10b88a 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -5376,6 +5376,9 @@ "properties": { "pkt_too_small": { "type": "integer" + }, + "unknown_ethertype": { + "type": "integer" } }, "additionalProperties": false diff --git a/rules/decoder-events.rules b/rules/decoder-events.rules index 092eebdb2755..1247b0ee2673 100644 --- a/rules/decoder-events.rules +++ b/rules/decoder-events.rules @@ -71,6 +71,7 @@ alert pkthdr any any -> any any (msg:"SURICATA UDP header length too small"; dec alert pkthdr any any -> any any (msg:"SURICATA UDP invalid length field in the header"; decode-event:udp.len_invalid; classtype:protocol-command-decode; sid:2200120; rev:2;) alert pkthdr any any -> any any (msg:"SURICATA SLL packet too small"; decode-event:sll.pkt_too_small; classtype:protocol-command-decode; sid:2200041; rev:2;) alert pkthdr any any -> any any (msg:"SURICATA Ethernet packet too small"; decode-event:ethernet.pkt_too_small; classtype:protocol-command-decode; sid:2200042; rev:2;) +alert pkthdr any any -> any any (msg:"SURICATA Ethertype unknown"; decode-event:ethernet.unknown_ethertype; threshold: type limit, track by_rule, seconds 60, count 1; classtype:protocol-command-decode; sid:2200121; rev:1;) alert pkthdr any any -> any any (msg:"SURICATA PPP packet too small"; decode-event:ppp.pkt_too_small; classtype:protocol-command-decode; sid:2200043; rev:2;) alert pkthdr any any -> any any (msg:"SURICATA PPP VJU packet too small"; decode-event:ppp.vju_pkt_too_small; classtype:protocol-command-decode; sid:2200044; rev:2;) alert pkthdr any any -> any any (msg:"SURICATA PPP IPv4 packet too small"; decode-event:ppp.ip4_pkt_too_small; classtype:protocol-command-decode; sid:2200045; rev:2;) @@ -151,5 +152,5 @@ alert pkthdr any any -> any any (msg:"SURICATA CHDLC packet too small"; decode-e alert pkthdr any any -> any any (msg:"SURICATA packet with too many layers"; decode-event:too_many_layers; classtype:protocol-command-decode; sid:2200116; rev:1;) -# next sid is 2200121 +# next sid is 2200122 diff --git a/src/decode-events.c b/src/decode-events.c index 513969b0a75d..d6a4faa271f8 100644 --- a/src/decode-events.c +++ b/src/decode-events.c @@ -286,6 +286,10 @@ const struct DecodeEvents_ DEvents[] = { "decoder.ethernet.pkt_too_small", ETHERNET_PKT_TOO_SMALL, }, + { + "decoder.ethernet.unknown_ethertype", + ETHERNET_UNKNOWN_ETHERTYPE, + }, /* PPP EVENTS */ { diff --git a/src/decode-events.h b/src/decode-events.h index e61668976d1d..26b23af7b177 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -109,7 +109,8 @@ enum { SLL_PKT_TOO_SMALL, /**< sll packet smaller than minimum size */ /* ETHERNET EVENTS */ - ETHERNET_PKT_TOO_SMALL, /**< ethernet packet smaller than minimum size */ + ETHERNET_PKT_TOO_SMALL, /**< ethernet packet smaller than minimum size */ + ETHERNET_UNKNOWN_ETHERTYPE, /**< ethertype unknown/unhandled*/ /* PPP EVENTS */ PPP_PKT_TOO_SMALL, /**< ppp packet smaller than minimum size */ diff --git a/src/decode.c b/src/decode.c index 927791b08b98..ad55f943f0ce 100644 --- a/src/decode.c +++ b/src/decode.c @@ -208,6 +208,9 @@ void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p) if (p->flags & PKT_IS_INVALID) { StatsIncr(tv, dtv->counter_invalid); } + if (p->flags & PKT_IS_UNKNOWN) { + StatsIncr(tv, dtv->counter_ethertype_unknown); + } } void PacketUpdateEngineEventCounters(ThreadVars *tv, diff --git a/src/decode.h b/src/decode.h index b7398bc2a0d6..20fa6ebf16eb 100644 --- a/src/decode.h +++ b/src/decode.h @@ -1165,7 +1165,11 @@ void DecodeUnregisterCounters(void); ENGINE_SET_EVENT(p, e); \ } while(0) - +#define ENGINE_SET_UNKNOWN_EVENT(p, e) \ + do { \ + p->flags |= PKT_IS_UNKNOWN; \ + ENGINE_SET_EVENT(p, e); \ + } while (0) #define ENGINE_ISSET_EVENT(p, e) ({ \ int r = 0; \ @@ -1322,6 +1326,9 @@ void DecodeUnregisterCounters(void); #define PKT_FIRST_ALERTS BIT_U32(29) #define PKT_FIRST_TAG BIT_U32(30) +/** Unknown/unsupported */ +#define PKT_IS_UNKNOWN BIT_U32(31) + /** \brief return 1 if the packet is a pseudo packet */ #define PKT_IS_PSEUDOPKT(p) \ ((p)->flags & (PKT_PSEUDO_STREAM_END|PKT_PSEUDO_DETECTLOG_FLUSH)) @@ -1508,7 +1515,7 @@ static inline bool DecodeNetworkLayer(ThreadVars *tv, DecodeThreadVars *dtv, break; default: SCLogDebug("unknown ether type: %" PRIx16 "", proto); - StatsIncr(tv, dtv->counter_ethertype_unknown); + ENGINE_SET_UNKNOWN_EVENT(p, ETHERNET_UNKNOWN_ETHERTYPE); return false; } return true; From 359ec44d1644651d77b83e9c957d48d43f230a13 Mon Sep 17 00:00:00 2001 From: Jeff Lucovsky Date: Sun, 7 Jul 2024 09:24:33 -0400 Subject: [PATCH 2/2] doc/threshold: Threshold keyword clarifications Issue: 7129 --- doc/userguide/rules/thresholding.rst | 166 +++++++++++++++------------ 1 file changed, 91 insertions(+), 75 deletions(-) diff --git a/doc/userguide/rules/thresholding.rst b/doc/userguide/rules/thresholding.rst index ea2ea2806abd..a75e6fab7ec8 100644 --- a/doc/userguide/rules/thresholding.rst +++ b/doc/userguide/rules/thresholding.rst @@ -1,3 +1,5 @@ +.. role:: example-rule-emphasis + Thresholding Keywords ===================== @@ -7,98 +9,122 @@ Thresholding can be configured per rule and also globally, see Thresholds are tracked in a hash table that is sized according to configuration, see: :ref:`suricata-yaml-thresholds`. -*Note: mixing rule and global thresholds is not supported in 1.3 and -before. See bug #425.* For the state of the support in 1.4 see -:ref:`global-thresholds-vs-rule-thresholds` +**IMPORTANT** for both ``threshold`` and ``detection_filter`` keywords + +.. note:: + + Rules that contain ``flowbits``, ``flowints``, etc will still have those actions performed when the rule + contains one of the ``threshold`` keywords. Those actions are not subject to the threshold limits. + + Rule actions ``drop`` (IPS mode) and ``reject`` are applied to each packet + (not only the one that meets the limit condition). threshold --------- -The threshold keyword can be used to control the rule's alert -frequency. It has 3 modes: threshold, limit and both. +The ``threshold`` keyword can be used to control the rule's alert +frequency. There are four threshold modes: + +#. threshold +#. limit +#. both +#. backoff Syntax:: threshold: type , track , count , |multiplier > +Specify ``seconds`` to control the number of alerts per time period. + type "threshold" ~~~~~~~~~~~~~~~~ -This type can be used to set a minimum threshold for a rule before it -generates alerts. A threshold setting of N means on the Nth time the -rule matches an alert is generated. +This type sets a minimum threshold for a rule before it generates alerts. -Example:: +A threshold setting with a ``count`` value of ``C`` will generate an alert +the ``Cth`` time the alert matches. If ``seconds`` is specified, an +alert is generated when ``count`` matches have occurred within ``N`` seconds. - alert tcp !$HOME_NET any -> $HOME_NET 25 (msg:"ET POLICY Inbound Frequent Emails - Possible Spambot Inbound"; \ - flow:established; content:"mail from|3a|"; nocase; \ - threshold: type threshold, track by_src, count 10, seconds 60; \ - reference:url,doc.emergingthreats.net/2002087; classtype:misc-activity; sid:2002087; rev:10;) +Syntax:: + + threshold: type threshold, track by_flow, count , seconds ; -This signature only generates an alert if we get 10 inbound emails or -more from the same server in a time period of one minute. +Example: -If a signature sets a flowbit, flowint, etc. those actions are still -performed for each of the matches. +.. container:: example-rule - *Rule actions drop (IPS mode) and reject are applied to each packet - (not only the one that meets the threshold condition).* + alert tcp !$HOME_NET any -> $HOME_NET 25 (msg:"ET POLICY Inbound Frequent Emails - Possible Spambot Inbound"; + flow:established; content:"mail from|3a|"; nocase; + :example-rule-emphasis:`threshold: type threshold, track by_src, count 10, seconds 60;` + reference:url,doc.emergingthreats.net/2002087; classtype:misc-activity; sid:2002087; rev:10;) + +This signature generates an alert if there are 10 or more inbound emails from the same server within +one minute. type "limit" ~~~~~~~~~~~~ -This type can be used to make sure you're not getting flooded with -alerts. If set to limit N, it alerts at most N times. +The ``limit`` type prevents a flood of alerts by limiting the number of alerts. +A limit with a count of ``N`` won't generate more than ``N`` alerts. + +Limit the number of alerts per time period by specifying ``seconds`` with +``count.`` + +Syntax:: -Example:: + threshold: type limit, track by_dst, count , seconds ; - alert http $HOME_NET any -> any $HTTP_PORTS (msg:"ET USER_AGENTS Internet Explorer 6 in use - Significant Security Risk"; \ - flow:to_server,established; content:"|0d 0a|User-Agent|3a| Mozilla/4.0 (compatible|3b| MSIE 6.0|3b|"; \ - threshold: type limit, track by_src, seconds 180, count 1; \ - reference:url,doc.emergingthreats.net/2010706; classtype:policy-violation; sid:2010706; rev:7;) +Example: -In this example at most 1 alert is generated per host within a period -of 3 minutes if MSIE 6.0 is detected. +.. container:: example-rule -If a signature sets a flowbit, flowint, etc. those actions are still -performed for each of the matches. + alert http $HOME_NET any -> any any (msg:"ET INFO Internet Explorer 6 in use - Significant Security Risk"; + flow:established,to_server; http.user_agent; content:"Mozilla/4.0 (compatible|3b| MSIE 6.0|3b|"; + :example-rule-emphasis:`threshold: type limit, track by_src, seconds 180, count 1;` + classtype:policy-violation; sid:2010706; rev:10; metadata:created_at 2010_07_30, updated_at 2024_03_16;) - *Rule actions drop (IPS mode) and reject are applied to each packet - (not only the one that meets the limit condition).* +In this example, at most 1 alert is generated per host within a period +of 3 minutes if "MSIE 6.0" is detected. type "both" ~~~~~~~~~~~ -This type is a combination of the "threshold" and "limit" types. It -applies both thresholding and limiting. +This type combines ``threshold`` and ``limit`` to control when alerts +are generated. -Example:: +Syntax:: - alert tcp $HOME_NET 5060 -> $EXTERNAL_NET any (msg:"ET VOIP Multiple Unauthorized SIP Responses TCP"; \ - flow:established,from_server; content:"SIP/2.0 401 Unauthorized"; depth:24; \ - threshold: type both, track by_src, count 5, seconds 360; \ - reference:url,doc.emergingthreats.net/2003194; classtype:attempted-dos; sid:2003194; rev:6;) + threshold: type both, track by_flow, count , multiplier ; + +Example: + +.. container:: example-rule -This alert will only generate an alert if within 6 minutes there have -been 5 or more "SIP/2.0 401 Unauthorized" responses, and it will alert -only once in that 6 minutes. + alert tcp $HOME_NET 5060 -> $EXTERNAL_NET any (msg:"ET VOIP Multiple Unauthorized SIP Responses TCP"; + flow:established,from_server; content:"SIP/2.0 401 Unauthorized"; depth:24; + :example-rule-emphasis:`threshold: type both, track by_src, count 5, seconds 360;` + reference:url,doc.emergingthreats.net/2003194; classtype:attempted-dos; sid:2003194; rev:6;) -If a signature sets a flowbit, flowint, etc. those actions are still -performed for each of the matches. +This rule will generate at most one alert every 6 minutes if there have been 5 or more occurrences +of "SIP2.0 401 Unauthorized" responses. - *Rule actions drop (IPS mode) and reject are applied to each packet.* +The ``type backoff`` section describes the ``multiplier`` keyword. type "backoff" ~~~~~~~~~~~~~~ -Allow limiting of alert output by using a backoff algorithm. +This type limits the alert output by using a backoff algorithm between alerts. + +.. note:: + + ``backoff`` can only be used with ``track by_flow`` Syntax:: threshold: type backoff, track by_flow, count , multiplier ; ``track``: backoff is only supported for ``by_flow`` -``count``: number of alerts before the first match is logged +``count``: number of alerts before the first match generates an alert. ``multiplier``: value to multiply ``count`` with each time the next value is reached A count of 1 with a multiplier of 10 would generate alerts for matching packets:: @@ -117,14 +143,9 @@ In the following example, the ``pkt_invalid_ack`` would only lead to alerts the .. container:: example-rule - alert tcp any any -> any any (stream-event:pkt_invalid_ack; \ - :example-rule-options:`threshold:type backoff, track by_flow, count 1, multiplier 10;` - sid:2210045; rev:2;) - -If a signature sets a flowbit, flowint, etc. those actions are still -performed for each of the matches. - - *Rule actions drop (IPS mode) and reject are applied to each matching packet.* + alert tcp any any -> any any (stream-event:pkt_invalid_ack; + :example-rule-emphasis:`threshold:type backoff, track by_flow, count 1, multiplier 10;` + sid:2210045; rev:2;) track @@ -150,31 +171,26 @@ track detection_filter ---------------- -The detection_filter keyword can be used to alert on every match after -a threshold has been reached. It differs from the threshold with type -threshold in that it generates an alert for each rule match after the -initial threshold has been reached, where the latter will reset it's -internal counter and alert again when the threshold has been reached -again. +The ``detection_filter`` keyword can be used to alert on every match after +an initial threshold has been reached. It differs from ``threshold`` with type +``threshold`` in that it generates an alert for each rule match after the +initial threshold has been reached, where the latter will reset its +internal counter and alert each time the threshold has been reached. Syntax:: detection_filter: track , count , seconds -Example:: - - alert http $EXTERNAL_NET any -> $HOME_NET any \ - (msg:"ET WEB_SERVER WebResource.axd access without t (time) parameter - possible ASP padding-oracle exploit"; \ - flow:established,to_server; content:"GET"; http_method; content:"WebResource.axd"; http_uri; nocase; \ - content:!"&t="; http_uri; nocase; content:!"&|3b|t="; http_uri; nocase; \ - detection_filter:track by_src,count 15,seconds 2; \ - reference:url,netifera.com/research/; reference:url,www.microsoft.com/technet/security/advisory/2416728.mspx; \ - classtype:web-application-attack; sid:2011807; rev:5;) +Example: -Alerts each time after 15 or more matches have occurred within 2 seconds. +.. container:: example-rule -If a signature sets a flowbit, flowint, etc. those actions are still -performed for each of the matches. + alert http $EXTERNAL_NET any -> $HOME_NET any + (msg:"ET WEB_SERVER WebResource.axd access without t (time) parameter - possible ASP padding-oracle exploit"; + flow:established,to_server; content:"GET"; http_method; content:"WebResource.axd"; http_uri; nocase; + content:!"&t="; http_uri; nocase; content:!"&|3b|t="; http_uri; nocase; + :example-rule-emphasis:`detection_filter:track by_src,count 15,seconds 2;` + reference:url,netifera.com/research/; reference:url,www.microsoft.com/technet/security/advisory/2416728.mspx; + classtype:web-application-attack; sid:2011807; rev:5;) - *Rule actions drop (IPS mode) and reject are applied to each packet - that generate an alert* +This rule will generate alerts are 15 or more matches have occurred within 2 seconds.