CVE-2017-15377 (published 2017-10-23T08:29Z)

In Suricata before 4.x, it was possible to trigger lots of redundant checks on the content of crafted network traffic with a certain signature, because of DetectEngineContentInspection in detect-engine-content-inspection.c. The search engine doesn't stop when it should after no match is found; instead, it stops only upon reaching inspection-recursion-limit (3000 by default).

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/OISF/suricata
commit_details: repo_url: https://github.com/OISF/suricata
author: Victor Julien
author_date: 2017-03-03 15:38:43+01:00
msg: detect: avoid needless recursive scanning

Don't recursively inspect a detect list if the recursion
doesn't increase chance of success.
repository: repo_url: https://github.com/OISF/suricata
repo_name: OISF/suricata
description: Suricata is a network Intrusion Detection System, Intrusion Prevention System and Network Security Monitoring engine developed by the OISF and the Suricata community.
repo_language: C
owner: OISF
file_changes: filename: detect-engine-content-inspection.c
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2011 Open Information Security Foundation
+/* Copyright (C) 2007-2017 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -286,6 +286,11 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
             SCLogDebug("found %p cd negated %s", found, cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
 
             if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
+                if ((cd->flags & (DETECT_CONTENT_DISTANCE|DETECT_CONTENT_WITHIN)) == 0) {
+                    /* independent match from previous matches, so failure is fatal */
+                    det_ctx->discontinue_matching = 1;
+                }
+
                 goto no_match;
             } else if (found == NULL && (cd->flags & DETECT_CONTENT_NEGATED)) {
                 goto match;
@@ -310,16 +315,10 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
                         SCLogWarning(SC_ERR_INVALID_VALUE, "Can't modify payload without packet");
                     }
                 }
-                if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
-                    SCLogDebug("no relative match coming up, so this is a match");
-                    goto match;
-                }
 
-                /* bail out if we have no next match. Technically this is an
-                 * error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
-                 * flag set. */
+                /* if this is the last match we're done */
                 if (smd->is_last) {
-                    goto no_match;
+                    goto match;
                 }
 
                 SCLogDebug("content %"PRIu32, cd->id);
@@ -333,9 +332,21 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
                 if (r == 1) {
                     SCReturnInt(1);
                 }
+                SCLogDebug("no match for 'next sm'");
 
-                if (det_ctx->discontinue_matching)
+                if (det_ctx->discontinue_matching) {
+                    SCLogDebug("'next sm' said to discontinue this right now");
                     goto no_match;
+                }
+
+                /* no match and no reason to look for another instance */
+                if ((cd->flags & DETECT_CONTENT_RELATIVE_NEXT) == 0) {
+                    SCLogDebug("'next sm' does not depend on me, so we can give up");
+                    det_ctx->discontinue_matching = 1;
+                    goto no_match;
+                }
+
+                SCLogDebug("'next sm' depends on me %p, lets see what we can do (flags %u)", cd, cd->flags);
 
                 /* set the previous match offset to the start of this match + 1 */
                 prev_offset = (match_offset - (cd->content_len - 1));

programming_language: C