]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Add krb5_msg_type detection keyword
authorPierre Chifflier <chifflier@wzdftpd.net>
Sat, 5 May 2018 14:06:54 +0000 (16:06 +0200)
committerPierre Chifflier <chifflier@wzdftpd.net>
Wed, 13 Jun 2018 08:25:40 +0000 (10:25 +0200)
doc/userguide/rules/index.rst
doc/userguide/rules/kerberos-keywords.rst [new file with mode: 0644]
rust/src/krb/detect.rs [new file with mode: 0644]
rust/src/krb/mod.rs
src/Makefile.am
src/detect-engine-register.c
src/detect-engine-register.h
src/detect-krb5-msgtype.c [new file with mode: 0644]
src/detect-krb5-msgtype.h [new file with mode: 0644]

index 55f6e8aa1caac9498e6ebf20f5bb3f513565a5df..2fa4e639b83f5022ea2d4b633b1c67a54982a65f 100644 (file)
@@ -18,6 +18,7 @@ Suricata Rules
    dnp3-keywords
    enip-keyword
    ftp-keywords
+   kerberos-keywords
    app-layer
    xbits
    thresholding
diff --git a/doc/userguide/rules/kerberos-keywords.rst b/doc/userguide/rules/kerberos-keywords.rst
new file mode 100644 (file)
index 0000000..7e295de
--- /dev/null
@@ -0,0 +1,25 @@
+Kerberos Keywords
+=================
+
+krb5_msg_type
+-------------
+
+Kerberos message type (integer).
+
+Values are defined in RFC4120. Common values are
+
+* 10 (AS-REQ)
+* 11 (AS-REP)
+* 12 (TGS-REQ)
+* 13 (TGS-REP)
+* 14 (AP-REQ)
+* 15 (AP-REP)
+* 30 (ERROR)
+
+Syntax::
+
+ krb5_msg_type:<number>
+
+Signature example::
+
+ alert krb5 any any -> any any (msg:"Kerberos 5 AS-REQ message"; krb5_msg_type:10; sid:3; rev:1;)
diff --git a/rust/src/krb/detect.rs b/rust/src/krb/detect.rs
new file mode 100644 (file)
index 0000000..fe45e24
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 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.
+ */
+
+// written by Pierre Chifflier  <chifflier@wzdftpd.net>
+
+use libc;
+
+use krb::krb5::KRB5Transaction;
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_krb5_tx_get_msgtype(tx:  &mut KRB5Transaction,
+                                                ptr: *mut libc::uint32_t)
+{
+    *ptr = tx.msg_type.0;
+}
index fea4d5590696449f41c02aa823be563d159c4a97..c8be867a09363bf2ccff16c685fd6fba174eba7b 100644 (file)
@@ -18,4 +18,5 @@
 // written by Pierre Chifflier  <chifflier@wzdftpd.net>
 
 pub mod krb5;
+pub mod detect;
 pub mod log;
index 38aa0f82e82cfeee1eb18acd1812095907011297..7cd86bc4672a123cfa6052ea5aaf804da1cdaea9 100644 (file)
@@ -213,6 +213,7 @@ detect-ipproto.c detect-ipproto.h \
 detect-iprep.c detect-iprep.h \
 detect-isdataat.c detect-isdataat.h \
 detect-itype.c detect-itype.h \
+detect-krb5-msgtype.c detect-krb5-msgtype.h \
 detect-l3proto.c detect-l3proto.h \
 detect-lua.c detect-lua.h \
 detect-lua-extensions.c detect-lua-extensions.h \
index f30c9b7d07d9550c522666e1ef142bbf143b7448..2537ea97e3a4407852d208ebd235c5ea2035067c 100644 (file)
 #include "detect-geoip.h"
 #include "detect-app-layer-protocol.h"
 #include "detect-template.h"
+#include "detect-krb5-msgtype.h"
 #include "detect-target.h"
 #include "detect-template-buffer.h"
 #include "detect-bypass.h"
@@ -490,6 +491,7 @@ void SigTableSetup(void)
     DetectBase64DecodeRegister();
     DetectBase64DataRegister();
     DetectTemplateRegister();
+    DetectKrb5MsgTypeRegister();
     DetectTargetRegister();
     DetectTemplateBufferRegister();
     DetectBypassRegister();
index 0e69c08629dae0dd614a9087c3a90ce0ccf463fb..cc27440737fbaf8a7627bafa1939dfee3f65d535 100644 (file)
@@ -197,6 +197,8 @@ enum {
     DETECT_BASE64_DECODE,
     DETECT_BASE64_DATA,
 
+    DETECT_AL_KRB5_MSGTYPE,
+
     DETECT_TEMPLATE,
     DETECT_FTPDATA,
     DETECT_TARGET,
diff --git a/src/detect-krb5-msgtype.c b/src/detect-krb5-msgtype.c
new file mode 100644 (file)
index 0000000..d1a2763
--- /dev/null
@@ -0,0 +1,272 @@
+/* Copyright (C) 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.
+ */
+
+/**
+ * \file
+ *
+ * \author Pierre Chifflier <chifflier@wzdftpd.net>
+ */
+
+#include "suricata-common.h"
+#include "util-unittest.h"
+
+#include "detect-parse.h"
+#include "detect-engine.h"
+
+#include "detect-krb5-msgtype.h"
+
+#ifdef HAVE_RUST
+
+#include "app-layer-krb5.h"
+#include "rust-krb-detect-gen.h"
+
+/**
+ * \brief Regex for parsing our keyword options
+ */
+#define PARSE_REGEX  "^\\s*([A-z0-9\\.]+|\"[A-z0-9_\\.]+\")\\s*$"
+static pcre *parse_regex;
+static pcre_extra *parse_regex_study;
+
+/* Prototypes of functions registered in DetectKrb5MsgTypeRegister below */
+static int DetectKrb5MsgTypeMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *,
+                                   uint8_t, void *, void *, const Signature *,
+                                   const SigMatchCtx *);
+static int DetectKrb5MsgTypeSetup (DetectEngineCtx *, Signature *, const char *);
+static void DetectKrb5MsgTypeFree (void *);
+static void DetectKrb5MsgTypeRegisterTests (void);
+
+static int DetectEngineInspectKRB5Generic(ThreadVars *tv,
+        DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
+        const Signature *s, const SigMatchData *smd,
+        Flow *f, uint8_t flags, void *alstate,
+        void *txv, uint64_t tx_id);
+
+static int g_krb5_msg_type_list_id = 0;
+
+/**
+ * \brief Registration function for krb5_msg_type: keyword
+ *
+ * This function is called once in the 'lifetime' of the engine.
+ */
+void DetectKrb5MsgTypeRegister(void) {
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].name = "krb5_msg_type";
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].desc = "match Kerberos 5 message type";
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].url = DOC_URL DOC_VERSION "/rules/kerberos-keywords.html#krb5_msg_type";
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].Match = NULL;
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].AppLayerTxMatch = DetectKrb5MsgTypeMatch;
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].Setup = DetectKrb5MsgTypeSetup;
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].Free = DetectKrb5MsgTypeFree;
+    sigmatch_table[DETECT_AL_KRB5_MSGTYPE].RegisterTests = DetectKrb5MsgTypeRegisterTests;
+
+    DetectAppLayerInspectEngineRegister("krb5_msg_type",
+            ALPROTO_KRB5, SIG_FLAG_TOSERVER, 0,
+            DetectEngineInspectKRB5Generic);
+
+    DetectAppLayerInspectEngineRegister("krb5_msg_type",
+            ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0,
+            DetectEngineInspectKRB5Generic);
+
+    /* set up the PCRE for keyword parsing */
+    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
+
+    g_krb5_msg_type_list_id = DetectBufferTypeRegister("krb5_msg_type");
+    SCLogDebug("g_krb5_msg_type_list_id %d", g_krb5_msg_type_list_id);
+}
+
+static int DetectEngineInspectKRB5Generic(ThreadVars *tv,
+        DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
+        const Signature *s, const SigMatchData *smd,
+        Flow *f, uint8_t flags, void *alstate,
+        void *txv, uint64_t tx_id)
+{
+    return DetectEngineInspectGenericList(tv, de_ctx, det_ctx, s, smd,
+                                          f, flags, alstate, txv, tx_id);
+}
+
+/**
+ * \brief This function is used to match KRB5 rule option on a packet
+ *
+ * \param t pointer to thread vars
+ * \param det_ctx pointer to the pattern matcher thread
+ * \param p pointer to the current packet
+ * \param m pointer to the sigmatch with context that we will cast into DetectKrb5Data
+ *
+ * \retval 0 no match
+ * \retval 1 match
+ */
+static int DetectKrb5MsgTypeMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
+                                   Flow *f, uint8_t flags, void *state,
+                                   void *txv, const Signature *s,
+                                   const SigMatchCtx *ctx)
+{
+    uint32_t msg_type;
+    const DetectKrb5MsgTypeData *dd = (const DetectKrb5MsgTypeData *)ctx;
+
+    SCEnter();
+
+    rs_krb5_tx_get_msgtype(txv, &msg_type);
+
+    if (dd->msg_type == msg_type)
+        SCReturnInt(1);
+
+    SCReturnInt(0);
+}
+
+/**
+ * \brief This function is used to parse options passed via krb5_msgtype: keyword
+ *
+ * \param krb5str Pointer to the user provided krb5_msg_type options
+ *
+ * \retval krb5d pointer to DetectKrb5Data on success
+ * \retval NULL on failure
+ */
+static DetectKrb5MsgTypeData *DetectKrb5MsgTypeParse (const char *krb5str)
+{
+    DetectKrb5MsgTypeData *krb5d = NULL;
+    char arg1[4] = "";
+#define MAX_SUBSTRINGS 30
+    int ret = 0, res = 0;
+    int ov[MAX_SUBSTRINGS];
+
+    ret = pcre_exec(parse_regex, parse_regex_study,
+                    krb5str, strlen(krb5str),
+                    0, 0, ov, MAX_SUBSTRINGS);
+    if (ret != 2) {
+        SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
+        goto error;
+    }
+
+    res = pcre_copy_substring((char *) krb5str, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
+    if (res < 0) {
+        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
+        goto error;
+    }
+
+    krb5d = SCMalloc(sizeof (DetectKrb5MsgTypeData));
+    if (unlikely(krb5d == NULL))
+        goto error;
+    krb5d->msg_type = (uint8_t)atoi(arg1);
+
+    return krb5d;
+
+error:
+    if (krb5d)
+        SCFree(krb5d);
+    return NULL;
+}
+
+/**
+ * \brief parse the options from the 'krb5_msg_type' keyword in the rule into
+ *        the Signature data structure.
+ *
+ * \param de_ctx pointer to the Detection Engine Context
+ * \param s pointer to the Current Signature
+ * \param krb5str pointer to the user provided options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectKrb5MsgTypeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *krb5str)
+{
+    DetectKrb5MsgTypeData *krb5d = NULL;
+    SigMatch *sm = NULL;
+
+    if (DetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0)
+        return -1;
+
+    krb5d = DetectKrb5MsgTypeParse(krb5str);
+    if (krb5d == NULL)
+        goto error;
+
+    sm = SigMatchAlloc();
+    if (sm == NULL)
+        goto error;
+
+    sm->type = DETECT_AL_KRB5_MSGTYPE;
+    sm->ctx = (void *)krb5d;
+
+    s->flags |= SIG_FLAG_STATE_MATCH;
+    SigMatchAppendSMToList(s, sm, g_krb5_msg_type_list_id);
+
+    return 0;
+
+error:
+    if (krb5d != NULL)
+        DetectKrb5MsgTypeFree(krb5d);
+    if (sm != NULL)
+        SCFree(sm);
+    return -1;
+}
+
+/**
+ * \brief this function will free memory associated with DetectKrb5Data
+ *
+ * \param ptr pointer to DetectKrb5Data
+ */
+static void DetectKrb5MsgTypeFree(void *ptr) {
+    DetectKrb5MsgTypeData *krb5d = (DetectKrb5MsgTypeData *)ptr;
+
+    SCFree(krb5d);
+}
+
+#ifdef UNITTESTS
+
+/**
+ * \test description of the test
+ */
+
+static int DetectKrb5MsgTypeParseTest01 (void)
+{
+    DetectKrb5MsgTypeData *krb5d = DetectKrb5MsgTypeParse("10");
+    FAIL_IF_NULL(krb5d);
+    FAIL_IF(!(krb5d->msg_type == 10));
+    DetectKrb5MsgTypeFree(krb5d);
+    PASS;
+}
+
+static int DetectKrb5MsgTypeSignatureTest01 (void)
+{
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+
+    Signature *sig = DetectEngineAppendSig(de_ctx, "alert krb5 any any -> any any (krb5_msg_type:10; sid:1; rev:1;)");
+    FAIL_IF_NULL(sig);
+
+    DetectEngineCtxFree(de_ctx);
+    PASS;
+}
+
+#endif /* UNITTESTS */
+
+/**
+ * \brief this function registers unit tests for DetectKrb5MsgType
+ */
+static void DetectKrb5MsgTypeRegisterTests(void) {
+#ifdef UNITTESTS
+    UtRegisterTest("DetectKrb5MsgTypeParseTest01", DetectKrb5MsgTypeParseTest01);
+    UtRegisterTest("DetectKrb5MsgTypeSignatureTest01",
+                   DetectKrb5MsgTypeSignatureTest01);
+#endif /* UNITTESTS */
+}
+
+#else /* HAVE_RUST */
+
+void DetectKrb5MsgTypeRegister(void)
+{
+}
+
+#endif /* HAVE_RUST */
diff --git a/src/detect-krb5-msgtype.h b/src/detect-krb5-msgtype.h
new file mode 100644 (file)
index 0000000..76e8235
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (C) 2015-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
+ * 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 Pierre Chifflier <chifflier@wzdftpd.net>
+ */
+
+#ifndef __DETECT_KRB5_MSGTYPE_H__
+#define __DETECT_KRB5_MSGTYPE_H__
+
+typedef struct DetectKrb5MsgTypeData_ {
+    uint8_t msg_type;
+} DetectKrb5MsgTypeData;
+
+void DetectKrb5MsgTypeRegister(void);
+
+#endif /* __DETECT_KRB5_MSGTYPE_H__ */