]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: tcp.hdr sticky buffer
authorVictor Julien <victor@inliniac.net>
Wed, 19 Jun 2019 10:54:13 +0000 (12:54 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 21 Jun 2019 05:16:17 +0000 (07:16 +0200)
Sticky buffer to inspect the TCP header.

src/Makefile.am
src/detect-engine-mpm.c
src/detect-engine-register.c
src/detect-engine-register.h
src/detect-engine.c
src/detect-tcphdr.c [new file with mode: 0644]
src/detect-tcphdr.h [new file with mode: 0644]
src/tests/detect-tcphdr.c [new file with mode: 0644]

index f165b09665a08218c31493feffacecff8e6b6f1d..4376047498f38055a03fdfa0a72c51c03e2a4e9a 100644 (file)
@@ -248,6 +248,7 @@ detect-tag.c detect-tag.h \
 detect-target.c detect-target.h \
 detect-template.c detect-template.h \
 detect-template2.c detect-template2.h \
+detect-tcphdr.c detect-tcphdr.h \
 detect-tcpmss.c detect-tcpmss.h \
 detect-ftpdata.c detect-ftpdata.h \
 detect-template-rust-buffer.c detect-template-rust-buffer.h \
index 7bbb1b8f9d05cd44a22fc3343866f9262a194b6c..9ecf78f7dbfe4b522814b2cd1a9880da3e7c54c0 100644 (file)
@@ -42,6 +42,7 @@
 #include "util-memcpy.h"
 #include "conf.h"
 #include "detect-fast-pattern.h"
+#include "detect-tcphdr.h"
 
 #include "flow.h"
 #include "flow-var.h"
@@ -1384,6 +1385,11 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
             }
 
             SetRawReassemblyFlag(de_ctx, sh);
+
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_L4HDR_TS);
+            if (mpm_store != NULL) {
+                PrefilterTcpHeaderRegister(de_ctx, sh, mpm_store->mpm_ctx);
+            }
         }
         if (SGH_DIRECTION_TC(sh)) {
             mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TC);
@@ -1397,6 +1403,11 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
             }
 
             SetRawReassemblyFlag(de_ctx, sh);
+
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_L4HDR_TC);
+            if (mpm_store != NULL) {
+                PrefilterTcpHeaderRegister(de_ctx, sh, mpm_store->mpm_ctx);
+            }
        }
     } else if (SGH_PROTO(sh, IPPROTO_UDP)) {
         if (SGH_DIRECTION_TS(sh)) {
index 3d14d53da3499b2efddd64c6497f3da77b890524..7e74e025b148549eefb45165115f6e382c86ff06 100644 (file)
 #include "detect-app-layer-protocol.h"
 #include "detect-template.h"
 #include "detect-template2.h"
+#include "detect-tcphdr.h"
 #include "detect-tcpmss.h"
 #include "detect-krb5-cname.h"
 #include "detect-krb5-errcode.h"
@@ -524,6 +525,7 @@ void SigTableSetup(void)
     DetectBase64DataRegister();
     DetectTemplateRegister();
     DetectTemplate2Register();
+    DetectTcphdrRegister();
     DetectTcpmssRegister();
     DetectKrb5CNameRegister();
     DetectKrb5ErrCodeRegister();
index ef8d9f821e8fd864da3a1eae346c22c4bc93d681..76ee057933df9fcefbebc2727eae3e4ab608dfb1 100644 (file)
@@ -225,6 +225,7 @@ enum {
 
     DETECT_TEMPLATE,
     DETECT_TEMPLATE2,
+    DETECT_TCPHDR,
     DETECT_TCPMSS,
     DETECT_FTPDATA,
     DETECT_TARGET,
index 3b53f03c0051c6b496a2aebc39fe81c5477abc8e..6172341c9f1bad90da9efee8d95f1da62d91287f 100644 (file)
@@ -54,6 +54,7 @@
 #include "detect-byte-extract.h"
 #include "detect-content.h"
 #include "detect-uricontent.h"
+#include "detect-tcphdr.h"
 #include "detect-engine-threshold.h"
 #include "detect-engine-content-inspection.h"
 
@@ -1248,6 +1249,15 @@ int DetectEnginePktInspectionSetup(Signature *s)
         SCLogDebug("sid %u: DetectEngineInspectRulePayloadMatches appended", s->id);
     }
 
+    if (s->sm_arrays[DETECT_SM_LIST_L4HDR] &&
+            (s->proto.proto[IPPROTO_TCP / 8] & (1 << (IPPROTO_TCP % 8))))
+    {
+        if (DetectEnginePktInspectionAppend(s, DetectEngineInspectRuleTcpHeaderMatches,
+                s->sm_arrays[DETECT_SM_LIST_L4HDR]) < 0)
+            return -1;
+        SCLogDebug("sid %u: DetectEngineInspectRuleTcpHeaderMatches appended", s->id);
+    }
+
     if (s->sm_arrays[DETECT_SM_LIST_MATCH]) {
         if (DetectEnginePktInspectionAppend(s, DetectEngineInspectRulePacketMatches,
                 s->sm_arrays[DETECT_SM_LIST_MATCH]) < 0)
diff --git a/src/detect-tcphdr.c b/src/detect-tcphdr.c
new file mode 100644 (file)
index 0000000..bec4898
--- /dev/null
@@ -0,0 +1,168 @@
+/* Copyright (C) 2007-2019 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ *
+ */
+
+#include "suricata-common.h"
+
+#include "detect.h"
+#include "detect-parse.h"
+#include "detect-engine.h"
+#include "detect-engine-prefilter.h"
+#include "detect-engine-content-inspection.h"
+#include "detect-fast-pattern.h"
+#include "detect-tcphdr.h"
+
+/* prototypes */
+static int DetectTcphdrSetup (DetectEngineCtx *, Signature *, const char *);
+#ifdef UNITTESTS
+void DetectTcphdrRegisterTests (void);
+#endif
+
+/**
+ * \brief Registration function for tcphdr: keyword
+ */
+
+void DetectTcphdrRegister(void)
+{
+    sigmatch_table[DETECT_TCPHDR].name = "tcp.hdr";
+    sigmatch_table[DETECT_TCPHDR].desc = "sticky buffer to match on the TCP header";
+    sigmatch_table[DETECT_TCPHDR].url = DOC_URL DOC_VERSION "/rules/header-keywords.html#tcphdr";
+    sigmatch_table[DETECT_TCPHDR].Setup = DetectTcphdrSetup;
+    sigmatch_table[DETECT_TCPHDR].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
+#ifdef UNITTESTS
+    sigmatch_table[DETECT_TCPHDR].RegisterTests = DetectTcphdrRegisterTests;
+#endif
+    SupportFastPatternForSigMatchList(DETECT_SM_LIST_L4HDR, 2);
+    return;
+}
+
+/**
+ * \brief this function is used to atcphdrd the parsed tcphdr data into the current signature
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param tcphdrstr pointer to the user provided tcphdr options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectTcphdrSetup (DetectEngineCtx *de_ctx, Signature *s, const char *tcphdrstr)
+{
+    if (!(DetectProtoContainsProto(&s->proto, IPPROTO_TCP)))
+        return -1;
+
+    s->flags |= SIG_FLAG_REQUIRE_PACKET;
+
+    if (DetectBufferSetActiveList(s, DETECT_SM_LIST_L4HDR) < 0)
+        return -1;
+
+    return 0;
+}
+
+static void PrefilterTcpHeader(DetectEngineThreadCtx *det_ctx,
+        Packet *p, const void *pectx)
+{
+    SCEnter();
+
+    uint32_t hlen = TCP_GET_HLEN(p);
+    if (((uint8_t *)p->tcph + (ptrdiff_t)hlen) >
+            ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)))
+    {
+        SCLogDebug("data out of range: %p > %p",
+                ((uint8_t *)p->tcph + (ptrdiff_t)hlen),
+                ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)));
+        SCReturn;
+    }
+
+    const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
+    if (hlen < mpm_ctx->minlen)
+        SCReturn;
+
+    (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
+            &det_ctx->mtc, &det_ctx->pmq,
+            (uint8_t *)p->tcph, hlen);
+}
+
+int PrefilterTcpHeaderRegister(DetectEngineCtx *de_ctx,
+        SigGroupHead *sgh, MpmCtx *mpm_ctx)
+{
+    return PrefilterAppendEngine(de_ctx, sgh,
+            PrefilterTcpHeader, mpm_ctx, NULL, "tcp.hdr");
+}
+
+/**
+ *  \brief Do the content inspection & validation for a signature
+ *
+ *  \param det_ctx Detection engine thread context
+ *  \param s Signature to inspect
+ *  \param p Packet
+ *
+ *  \retval false no match
+ *  \retval true match
+ */
+bool DetectEngineInspectRuleTcpHeaderMatches(
+     ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
+     const Signature *s, const SigMatchData *sm_data,
+     Flow *f, Packet *p,
+     uint8_t *alert_flags)
+{
+    SCEnter();
+
+    BUG_ON(sm_data == NULL);
+    BUG_ON(sm_data != s->sm_arrays[DETECT_SM_LIST_L4HDR]);
+
+    if (!(PKT_IS_TCP(p))) {
+        SCReturnInt(false);
+    }
+    uint32_t hlen = TCP_GET_HLEN(p);
+    if (((uint8_t *)p->tcph + (ptrdiff_t)hlen) >
+            ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)))
+    {
+        SCLogDebug("data out of range: %p > %p",
+                ((uint8_t *)p->tcph + (ptrdiff_t)hlen),
+                ((uint8_t *)GET_PKT_DATA(p) + (ptrdiff_t)GET_PKT_LEN(p)));
+        SCReturnInt(false);
+    }
+
+#ifdef DEBUG
+    det_ctx->payload_persig_cnt++;
+    det_ctx->payload_persig_size += hlen;
+#endif
+    det_ctx->buffer_offset = 0;
+    det_ctx->discontinue_matching = 0;
+    det_ctx->inspection_recursion_counter = 0;
+    det_ctx->replist = NULL;
+
+    int r = DetectEngineContentInspection(det_ctx->de_ctx, det_ctx,
+            s, sm_data,
+            p, NULL, (uint8_t *)p->tcph, hlen, 0,
+            DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_HEADER);
+    if (r == 1) {
+        SCReturnInt(true);
+    }
+    SCReturnInt(false);
+}
+
+#ifdef UNITTESTS
+#include "tests/detect-tcphdr.c"
+#endif
diff --git a/src/detect-tcphdr.h b/src/detect-tcphdr.h
new file mode 100644 (file)
index 0000000..0bd1f94
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 2007-2019 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ */
+
+#ifndef _DETECT_TCPHDR_H
+#define _DETECT_TCPHDR_H
+
+int PrefilterTcpHeaderRegister(DetectEngineCtx *de_ctx,
+        SigGroupHead *sgh, MpmCtx *mpm_ctx);
+bool DetectEngineInspectRuleTcpHeaderMatches(
+     ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
+     const Signature *s, const SigMatchData *sm_data,
+     Flow *f, Packet *p,
+     uint8_t *alert_flags);
+void DetectTcphdrRegister(void);
+
+#endif /* _DETECT_TCPHDR_H */
diff --git a/src/tests/detect-tcphdr.c b/src/tests/detect-tcphdr.c
new file mode 100644 (file)
index 0000000..6faa0d7
--- /dev/null
@@ -0,0 +1,47 @@
+/* Copyright (C) 2007-2018 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "../suricata-common.h"
+
+#include "../detect.h"
+#include "../detect-parse.h"
+#include "../detect-engine-prefilter-common.h"
+
+#include "../detect-tcphdr.h"
+
+#include "../util-unittest.h"
+
+static int DetectTcphdrParseTest01 (void)
+{
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+
+    Signature *sig = DetectEngineAppendSig(de_ctx,
+            "alert tcp any any -> any any (tcp.hdr; content:\"A\"; sid:1; rev:1;)");
+    FAIL_IF_NULL(sig);
+
+    DetectEngineCtxFree(de_ctx);
+    PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTcphdr
+ */
+void DetectTcphdrRegisterTests(void)
+{
+    UtRegisterTest("DetectTcphdrParseTest01", DetectTcphdrParseTest01);
+}