]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app-layer: template for application layer content inspection
authorJason Ish <ish@unx.ca>
Tue, 1 Sep 2015 18:36:00 +0000 (12:36 -0600)
committerJason Ish <ish@unx.ca>
Fri, 11 Sep 2015 05:55:02 +0000 (23:55 -0600)
src/Makefile.am
src/detect-engine-content-inspection.h
src/detect-engine-state.h
src/detect-engine-template.c [new file with mode: 0644]
src/detect-engine-template.h [new file with mode: 0644]
src/detect-engine.c
src/detect-parse.c
src/detect-template-buffer.c [new file with mode: 0644]
src/detect-template-buffer.h [new file with mode: 0644]
src/detect.c
src/detect.h

index 9d3809c2f4036ea54441ab2eefe31829c3817b07..674043f5db72e8f04bb660dc79067662bedef459 100644 (file)
@@ -123,6 +123,7 @@ detect-engine-siggroup.c detect-engine-siggroup.h \
 detect-engine-sigorder.c detect-engine-sigorder.h \
 detect-engine-state.c detect-engine-state.h \
 detect-engine-tag.c detect-engine-tag.h \
+detect-engine-template.c detect-engine-template.h \
 detect-engine-threshold.c detect-engine-threshold.h \
 detect-engine-uri.c detect-engine-uri.h \
 detect-fast-pattern.c detect-fast-pattern.h \
@@ -195,6 +196,7 @@ detect-ssl-version.c detect-ssl-version.h \
 detect-stream_size.c detect-stream_size.h \
 detect-tag.c detect-tag.h \
 detect-template.c detect-template.h \
+detect-template-buffer.c detect-template-buffer.h \
 detect-threshold.c detect-threshold.h \
 detect-tls.c detect-tls.h \
 detect-tls-version.c detect-tls-version.h \
index 6d3accaaa324d338b93a77295d36e7959d161ddb..dc0b5026bee78d38233c318c6ef4b2cdf6318db3 100644 (file)
@@ -50,6 +50,7 @@ enum {
     DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRHHD,
     DETECT_ENGINE_CONTENT_INSPECTION_MODE_DNSQUERY,
     DETECT_ENGINE_CONTENT_INSPECTION_MODE_FD_SMTP,
+    DETECT_ENGINE_CONTENT_INSPECTION_MODE_TEMPLATE_BUFFER,
 };
 
 int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
index 51f67448e778709a63a4f9dc7f8e1ac7659e0d20..c8944cffd17cca5161d6503767bb2f8903d58e6c 100644 (file)
@@ -81,6 +81,7 @@
 #define DE_STATE_FLAG_FD_SMTP_INSPECT     (1 << 21)
 #define DE_STATE_FLAG_DNSREQUEST_INSPECT  (1 << 22)
 #define DE_STATE_FLAG_DNSRESPONSE_INSPECT (1 << 23)
+#define DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT (1 << 24)
 
 /* state flags */
 #define DETECT_ENGINE_STATE_FLAG_FILE_STORE_DISABLED 0x0001
diff --git a/src/detect-engine-template.c b/src/detect-engine-template.c
new file mode 100644 (file)
index 0000000..49c29c6
--- /dev/null
@@ -0,0 +1,46 @@
+/* Copyright (C) 2015 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 "stream.h"
+#include "detect-engine-content-inspection.h"
+
+#include "app-layer-template.h"
+
+int DetectEngineInspectTemplateBuffer(ThreadVars *tv, DetectEngineCtx *de_ctx,
+    DetectEngineThreadCtx *det_ctx, Signature *s, Flow *f, uint8_t flags,
+    void *alstate, void *txv, uint64_t tx_id)
+{
+    TemplateTransaction *tx = (TemplateTransaction *)txv;
+    int ret = 0;
+
+    if (flags & STREAM_TOSERVER && tx->request_buffer != NULL) {
+        ret = DetectEngineContentInspection(de_ctx, det_ctx, s,
+            s->sm_lists[DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH], f,
+            tx->request_buffer, tx->request_buffer_len, 0,
+            DETECT_ENGINE_CONTENT_INSPECTION_MODE_TEMPLATE_BUFFER, NULL);
+    }
+    else if (flags & STREAM_TOCLIENT && tx->response_buffer != NULL) {
+        ret = DetectEngineContentInspection(de_ctx, det_ctx, s,
+            s->sm_lists[DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH], f,
+            tx->response_buffer, tx->response_buffer_len, 0,
+            DETECT_ENGINE_CONTENT_INSPECTION_MODE_TEMPLATE_BUFFER, NULL);
+    }
+
+    SCLogNotice("Returning %d.", ret);
+    return ret;
+}
diff --git a/src/detect-engine-template.h b/src/detect-engine-template.h
new file mode 100644 (file)
index 0000000..61eb8d0
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (C) 2015 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.
+ */
+
+#ifndef __DETECT_TEMPLATE_ENGINE_H__
+#define __DETECT_TEMPLATE_ENGINE_H__
+
+int DetectEngineInspectTemplateBuffer(ThreadVars *, DetectEngineCtx *,
+    DetectEngineThreadCtx *, Signature *, Flow *, uint8_t, void *, void *,
+    uint64_t);
+
+#endif /* __DETECT_TEMPLATE_ENGINE_H__ */
index 7de049693f9752b920ca4b534aa3a3c3f04c5444..c6e1a83f4c5f24c157ca049d2181126b188b6282 100644 (file)
@@ -62,6 +62,7 @@
 #include "detect-engine-dns.h"
 #include "detect-engine-modbus.h"
 #include "detect-engine-filedata-smtp.h"
+#include "detect-engine-template.h"
 
 #include "detect-engine.h"
 #include "detect-engine-state.h"
@@ -285,6 +286,13 @@ void DetectEngineRegisterAppInspectionEngines(void)
           DE_STATE_FLAG_FD_SMTP_INSPECT,
           0,
           DetectEngineInspectSMTPFiledata },
+        /* Template. */
+        { IPPROTO_TCP,
+          ALPROTO_TEMPLATE,
+          DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
+          DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT,
+          0,
+          DetectEngineInspectTemplateBuffer },
     };
 
     struct tmp_t data_toclient[] = {
@@ -352,6 +360,13 @@ void DetectEngineRegisterAppInspectionEngines(void)
           DE_STATE_FLAG_DNSRESPONSE_INSPECT,
           1,
           DetectEngineInspectDnsResponse },
+        /* Template. */
+        { IPPROTO_TCP,
+          ALPROTO_TEMPLATE,
+          DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
+          DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT,
+          1,
+          DetectEngineInspectTemplateBuffer },
     };
 
     size_t i;
@@ -2630,6 +2645,9 @@ const char *DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
         case DETECT_SM_LIST_MODBUS_MATCH:
             return "modbus";
 
+        case DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH:
+            return "template_buffer";
+
         case DETECT_SM_LIST_POSTMATCH:
             return "post-match";
 
index d077791e345afd3abc93010e60efb09017f02489..fedfebe8648dbf5a6986812f40696a1c148a8c58 100644 (file)
@@ -1479,6 +1479,11 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr,
     if (sig->sm_lists[DETECT_SM_LIST_HRHHDMATCH])
         sig->flags |= SIG_FLAG_STATE_MATCH;
 
+    /* Template. */
+    if (sig->sm_lists[DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH]) {
+        sig->flags |= SIG_FLAG_STATE_MATCH;
+    }
+
     /* DNS */
     if (sig->sm_lists[DETECT_SM_LIST_DNSQUERYNAME_MATCH])
         sig->flags |= SIG_FLAG_STATE_MATCH;
diff --git a/src/detect-template-buffer.c b/src/detect-template-buffer.c
new file mode 100644 (file)
index 0000000..64f948c
--- /dev/null
@@ -0,0 +1,165 @@
+/* Copyright (C) 2015 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 Set up of the "template_buffer" keyword to allow content inspections
+ *    on the decoded template application layer buffers.
+ */
+
+#include "suricata-common.h"
+#include "detect.h"
+#include "app-layer-template.h"
+
+static int DetectTemplateBufferSetup(DetectEngineCtx *, Signature *, char *);
+static void DetectTemplateBufferRegisterTests(void);
+
+void DetectTemplateBufferRegister(void)
+{
+    sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].name = "template_buffer";
+    sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].desc =
+        "Template content modififier to match on the template buffers";
+    sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].alproto = ALPROTO_TEMPLATE;
+    sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].Setup = DetectTemplateBufferSetup;
+    sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].RegisterTests =
+        DetectTemplateBufferRegisterTests;
+
+    sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].flags |= SIGMATCH_NOOPT;
+    sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].flags |= SIGMATCH_PAYLOAD;
+
+    SCLogNotice("Template application layer detect registered.");
+}
+
+static int DetectTemplateBufferSetup(DetectEngineCtx *de_ctx, Signature *s,
+    char *str)
+{
+    s->list = DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH;
+    s->alproto = ALPROTO_TEMPLATE;
+    return 0;
+}
+
+#ifdef UNITTESTS
+
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+#include "app-layer-parser.h"
+#include "detect-engine.h"
+#include "detect-parse.h"
+#include "flow-util.h"
+#include "stream-tcp.h"
+
+static int DetectTemplateBufferTest(void)
+{
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+    DetectEngineThreadCtx *det_ctx = NULL;
+    DetectEngineCtx *de_ctx = NULL;
+    Flow f;
+    Packet *p;
+    TcpSession tcp;
+    ThreadVars tv;
+    Signature *s;
+
+    int result = 0;
+
+    uint8_t request[] = "Hello World!";
+
+    /* Setup flow. */
+    memset(&f, 0, sizeof(Flow));
+    memset(&tcp, 0, sizeof(TcpSession));
+    memset(&tv, 0, sizeof(ThreadVars));
+    p = UTHBuildPacket(request, sizeof(request), IPPROTO_TCP);
+    FLOW_INITIALIZE(&f);
+    f.alproto = ALPROTO_TEMPLATE;
+    f.protoctx = (void *)&tcp;
+    f.proto = IPPROTO_TCP;
+    f.flags |= FLOW_IPV4;
+    p->flow = &f;
+    p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+    p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
+    StreamTcpInitConfig(TRUE);
+
+    de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    /* This rule should match. */
+    s = DetectEngineAppendSig(de_ctx,
+        "alert tcp any any -> any any ("
+        "msg:\"TEMPLATE Test Rule\"; "
+        "template_buffer; content:\"World!\"; "
+        "sid:1; rev:1;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    /* This rule should not match. */
+    s = DetectEngineAppendSig(de_ctx,
+        "alert tcp any any -> any any ("
+        "msg:\"TEMPLATE Test Rule\"; "
+        "template_buffer; content:\"W0rld!\"; "
+        "sid:2; rev:1;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+    SCMutexLock(&f.m);
+    AppLayerParserParse(alp_tctx, &f, ALPROTO_TEMPLATE, STREAM_TOSERVER,
+        request, sizeof(request));
+    SCMutexUnlock(&f.m);
+
+    /* Check that we have app-layer state. */
+    if (f.alstate == NULL) {
+        goto end;
+    }
+
+    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+    if (!PacketAlertCheck(p, 1)) {
+        goto end;
+    }
+    if (PacketAlertCheck(p, 2)) {
+        goto end;
+    }
+
+    result = 1;
+end:
+    /* Cleanup. */
+    if (alp_tctx != NULL)
+        AppLayerParserThreadCtxFree(alp_tctx);
+    if (det_ctx != NULL)
+        DetectEngineThreadCtxDeinit(&tv, det_ctx);
+    if (de_ctx != NULL)
+        SigGroupCleanup(de_ctx);
+    if (de_ctx != NULL)
+        DetectEngineCtxFree(de_ctx);
+    StreamTcpFreeConfig(TRUE);
+    FLOW_DESTROY(&f);
+    UTHFreePacket(p);
+
+    return result;
+}
+
+#endif
+
+static void DetectTemplateBufferRegisterTests(void)
+{
+#ifdef UNITTESTS
+    UtRegisterTest("DetectTemplateBufferTest", DetectTemplateBufferTest, 1);
+#endif /* UNITTESTS */
+}
diff --git a/src/detect-template-buffer.h b/src/detect-template-buffer.h
new file mode 100644 (file)
index 0000000..8a2ab8b
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (C) 2015 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.
+ */
+
+#ifndef __DETECT_TEMPLATE_BUFFER_H__
+#define __DETECT_TEMPLATE_BUFFER_H__
+
+#include "app-layer-template.h"
+
+void DetectTemplateBufferRegister(void);
+
+#endif /* __DETECT_TEMPLATE_BUFFER_H__ */
index a1516200d01046916ce716851532a073089db3d5..e0b5bfd3f0cbc164741d09f39ca8eb23e2d123d3 100644 (file)
 #include "detect-dns-query.h"
 #include "detect-app-layer-protocol.h"
 #include "detect-template.h"
+#include "detect-template-buffer.h"
 
 #include "util-rule-vars.h"
 
 #include "app-layer-protos.h"
 #include "app-layer-htp.h"
 #include "app-layer-smtp.h"
+#include "app-layer-template.h"
 #include "detect-tls.h"
 #include "detect-tls-version.h"
 #include "detect-ssh-proto-version.h"
@@ -2431,6 +2433,10 @@ PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto, int has_state
                     SCLogDebug("packet/flow has smtp state");
                     (*mask) |= SIG_MASK_REQUIRE_SMTP_STATE;
                     break;
+                case ALPROTO_TEMPLATE:
+                    SCLogDebug("packet/flow has template state");
+                    (*mask) |= SIG_MASK_REQUIRE_TEMPLATE_STATE;
+                    break;
                 default:
                     SCLogDebug("packet/flow has other state");
                     break;
@@ -2668,6 +2674,10 @@ static int SignatureCreateMask(Signature *s)
         s->mask |= SIG_MASK_REQUIRE_SMTP_STATE;
         SCLogDebug("sig requires smtp state");
     }
+    if (s->alproto == ALPROTO_TEMPLATE) {
+        s->mask |= SIG_MASK_REQUIRE_TEMPLATE_STATE;
+        SCLogDebug("sig requires template state");
+    }
 
     if ((s->mask & SIG_MASK_REQUIRE_DCE_STATE) ||
         (s->mask & SIG_MASK_REQUIRE_HTTP_STATE) ||
@@ -2675,6 +2685,7 @@ static int SignatureCreateMask(Signature *s)
         (s->mask & SIG_MASK_REQUIRE_DNS_STATE) ||
         (s->mask & SIG_MASK_REQUIRE_FTP_STATE) ||
         (s->mask & SIG_MASK_REQUIRE_SMTP_STATE) ||
+        (s->mask & SIG_MASK_REQUIRE_TEMPLATE_STATE) ||
         (s->mask & SIG_MASK_REQUIRE_TLS_STATE))
     {
         s->mask |= SIG_MASK_REQUIRE_FLOW;
@@ -5238,6 +5249,7 @@ void SigTableSetup(void)
     DetectModbusRegister();
     DetectAppLayerProtocolRegister();
     DetectTemplateRegister();
+    DetectTemplateBufferRegister();
 }
 
 void SigTableRegisterTests(void)
index 236f69aa243bfa74112405da2c4087700f22c738..30adc9c4f81c74a618024a71b1f75c317a17744e 100644 (file)
@@ -126,6 +126,8 @@ enum DetectSigmatchListEnum {
 
     DETECT_SM_LIST_MODBUS_MATCH,
 
+    DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
+
     /* list for post match actions: flowbit set, flowint increment, etc */
     DETECT_SM_LIST_POSTMATCH,
 
@@ -305,6 +307,7 @@ typedef struct DetectPort_ {
 #define SIG_MASK_REQUIRE_DNS_STATE          (1<<10)
 #define SIG_MASK_REQUIRE_FTP_STATE          (1<<11)
 #define SIG_MASK_REQUIRE_SMTP_STATE         (1<<12)
+#define SIG_MASK_REQUIRE_TEMPLATE_STATE     (1<<13)
 
 /* for now a uint8_t is enough */
 #define SignatureMask uint16_t
@@ -1229,6 +1232,7 @@ enum {
     DETECT_XBITS,
 
     DETECT_TEMPLATE,
+    DETECT_AL_TEMPLATE_BUFFER,
 
     /* make sure this stays last */
     DETECT_TBLSIZE,