]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect-target: introduce new keyword
authorEric Leblond <eric@regit.org>
Fri, 16 Dec 2016 18:26:58 +0000 (19:26 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 12 Jun 2017 17:21:52 +0000 (19:21 +0200)
The target keyword allows rules writer to specify information about
target of the attack. Using this keyword in a signature causes
some fields to be added in the EVE output. It also fixes ambiguity
in the Prelude output.

src/Makefile.am
src/detect-target.c [new file with mode: 0644]
src/detect-target.h [new file with mode: 0644]
src/detect.c
src/detect.h

index b1d789f2e52e2e2b9261fb350cb3bb7a3fe8eb18..c2a95c08659043754e913993e8f1101dde29bd6f 100644 (file)
@@ -234,6 +234,7 @@ detect-ssl-state.c detect-ssl-state.h \
 detect-ssl-version.c detect-ssl-version.h \
 detect-stream_size.c detect-stream_size.h \
 detect-tag.c detect-tag.h \
+detect-target.c detect-target.h \
 detect-template.c detect-template.h \
 detect-template-buffer.c detect-template-buffer.h \
 detect-threshold.c detect-threshold.h \
diff --git a/src/detect-target.c b/src/detect-target.c
new file mode 100644 (file)
index 0000000..6a10671
--- /dev/null
@@ -0,0 +1,167 @@
+/* Copyright (C) 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 Eric Leblond <eric@regit.org>
+ *
+ * target keyword allow rules writer to specify information about target of the attack
+ */
+
+#include "suricata-common.h"
+#include "util-unittest.h"
+
+#include "detect-parse.h"
+#include "detect-engine.h"
+
+#include "detect-target.h"
+
+/**
+ * \brief Regex for parsing our keyword options
+ */
+#define PARSE_REGEX  "^\\s*(src_ip|dest_ip)\\s*$"
+
+static pcre *parse_regex;
+static pcre_extra *parse_regex_study;
+
+/* Prototypes of functions registered in DetectTargetRegister below */
+static int DetectTargetSetup (DetectEngineCtx *, Signature *, const char *);
+static void DetectTargetRegisterTests (void);
+
+/**
+ * \brief Registration function for target keyword
+ *
+ */
+void DetectTargetRegister(void) {
+    /* keyword name: this is how the keyword is used in a rule */
+    sigmatch_table[DETECT_TARGET].name = "target";
+    /* description: listed in "suricata --list-keywords=all" */
+    sigmatch_table[DETECT_TARGET].desc = "indicate to output module which side is the target of the attack";
+    /* link to further documentation of the keyword. Normally on the Suricata redmine/wiki */
+    sigmatch_table[DETECT_TARGET].url =  DOC_URL DOC_VERSION "/rules/meta.html#target";
+    /* match function is called when the signature is inspected on a packet */
+    sigmatch_table[DETECT_TARGET].Match = NULL;
+    /* setup function is called during signature parsing, when the target
+     * keyword is encountered in the rule */
+    sigmatch_table[DETECT_TARGET].Setup = DetectTargetSetup;
+    /* free function is called when the detect engine is freed. Normally at
+     * shutdown, but also during rule reloads. */
+    sigmatch_table[DETECT_TARGET].Free = NULL;
+    /* registers unittests into the system */
+    sigmatch_table[DETECT_TARGET].RegisterTests = DetectTargetRegisterTests;
+
+    /* set up the PCRE for keyword parsing */
+    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
+}
+
+/**
+ * \brief This function is used to parse target options passed via target: keyword
+ *
+ * \param targetstr Pointer to the user provided target options
+ *
+ * \retval targetd pointer to DetectTargetData on success
+ * \retval NULL on failure
+ */
+static int DetectTargetParse(Signature *s, const char *targetstr)
+{
+#define MAX_SUBSTRINGS 30
+    int ret = 0, res = 0;
+    int ov[MAX_SUBSTRINGS];
+    char value[10];
+
+    ret = pcre_exec(parse_regex, parse_regex_study,
+                    targetstr, strlen(targetstr), 0, 0, ov, MAX_SUBSTRINGS);
+    if (ret < 1) {
+        SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, targetstr);
+        return -1;
+    }
+
+    res = pcre_copy_substring(targetstr, ov, MAX_SUBSTRINGS, 1,
+                              value, sizeof(value));
+    if (res < 0) {
+        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
+        return -1;
+    }
+
+    /* now check key value */
+    if (!strcmp(value, "src_ip")) {
+        if (s->flags & SIG_FLAG_DEST_IS_TARGET) {
+            SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS,
+                       "Conflicting values of target keyword");
+            return -1;
+        }
+        s->flags |= SIG_FLAG_SRC_IS_TARGET;
+    } else if (!strcmp(value, "dest_ip")) {
+        if (s->flags & SIG_FLAG_SRC_IS_TARGET) {
+            SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS,
+                       "Conflicting values of target keyword");
+            return -1;
+        }
+        s->flags |= SIG_FLAG_DEST_IS_TARGET;
+    } else {
+        SCLogError(SC_ERR_INVALID_VALUE, "only 'src_ip' and 'dest_ip' are supported as target value");
+        return -1;
+    }
+    return 0;
+}
+
+/**
+ * \brief parse the options from the 'target' 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 targetstr pointer to the user provided target options
+ *
+ * \retval 0 on Success
+ * \retval -1 on Failure
+ */
+static int DetectTargetSetup(DetectEngineCtx *de_ctx, Signature *s, const char *targetstr)
+{
+    int ret = DetectTargetParse(s, targetstr);
+    if (ret < 0)
+        return -1;
+
+    return 0;
+}
+
+#ifdef UNITTESTS
+
+static int DetectTargetSignatureTest01(void)
+{
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+
+    Signature *sig = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any (target: dest_ip; sid:1; rev:1;)");
+    FAIL_IF_NULL(sig);
+
+    DetectEngineCtxFree(de_ctx);
+    PASS;
+}
+
+#endif /* UNITTESTS */
+
+/**
+ * \brief this function registers unit tests for DetectTarget
+ */
+void DetectTargetRegisterTests(void) {
+#ifdef UNITTESTS
+    UtRegisterTest("DetectTargetSignatureTest01",
+                   DetectTargetSignatureTest01);
+#endif /* UNITTESTS */
+}
diff --git a/src/detect-target.h b/src/detect-target.h
new file mode 100644 (file)
index 0000000..8c4e5c2
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 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 Eric Leblond <eric@regit.org>
+ */
+
+#ifndef __DETECT_TARGET_H__
+#define __DETECT_TARGET_H__
+
+void DetectTargetRegister(void);
+
+#endif /* __DETECT_TARGET_H__ */
index de83999ce1916ef57cd2b85ea3158d30defd8ad3..775e7240036abc192235cd13fd7a65aec1cb0fb6 100644 (file)
 #include "detect-geoip.h"
 #include "detect-app-layer-protocol.h"
 #include "detect-template.h"
+#include "detect-target.h"
 #include "detect-template-buffer.h"
 #include "detect-bypass.h"
 #include "detect-engine-content-inspection.h"
@@ -3930,6 +3931,7 @@ void SigTableSetup(void)
     DetectBase64DecodeRegister();
     DetectBase64DataRegister();
     DetectTemplateRegister();
+    DetectTargetRegister();
     DetectTemplateBufferRegister();
     DetectBypassRegister();
     DetectHttpRequestLineRegister();
index ccb99a017ec579de5ee2a188944a4f59e67d7a47..0abadec098f26cfb0a6af785ba868113621b3a8c 100644 (file)
@@ -240,6 +240,12 @@ typedef struct DetectPort_ {
 /** Proto detect only signature.
  *  Inspected once per direction when protocol detection is done. */
 #define SIG_FLAG_PDONLY                 (1<<24)
+/** Info for Source and Target identification */
+#define SIG_FLAG_SRC_IS_TARGET          (1<<25)
+/** Info for Source and Target identification */
+#define SIG_FLAG_DEST_IS_TARGET         (1<<26)
+
+#define SIG_FLAG_HAS_TARGET     (SIG_FLAG_DEST_IS_TARGET|SIG_FLAG_SRC_IS_TARGET)
 
 /* signature init flags */
 #define SIG_FLAG_INIT_DEONLY         1  /**< decode event only signature */
@@ -909,6 +915,7 @@ typedef struct DetectEngineThreadCtx_ {
     uint8_t *base64_decoded;
     int base64_decoded_len;
     int base64_decoded_len_max;
+
 #ifdef DEBUG
     uint64_t pkt_stream_add_cnt;
     uint64_t payload_mpm_cnt;
@@ -1342,6 +1349,7 @@ enum {
     DETECT_BASE64_DATA,
 
     DETECT_TEMPLATE,
+    DETECT_TARGET,
     DETECT_AL_TEMPLATE_BUFFER,
 
     DETECT_BYPASS,