]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
added optional selector to http_header
authorRuss Combs <rucombs@cisco.com>
Fri, 25 Jul 2014 21:36:40 +0000 (17:36 -0400)
committerRuss Combs <rucombs@cisco.com>
Fri, 25 Jul 2014 21:36:40 +0000 (17:36 -0400)
ChangeLog
lua/snort.lua
src/ips_options/CMakeLists.txt
src/ips_options/Makefile.am
src/ips_options/ips_http.cc
src/ips_options/ips_http_header.cc [new file with mode: 0644]

index 3298bcefcefe86f169b51b40c4e0785c025087da..c406707d4ea57f7a2c4b2fa751ec04aa2af8a465 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,7 @@
 -- added --rule "<rule>" for easy command line testing
 -- added --list-plugins to see which plugins don't have modules
 -- added helpers/markup.{h,cc}
+-- added optional header selector to http_header
 
 104
 -- changed configure --with-libpcre-* to --with-pcre-* for consistency
index 48c71717502db19cf2a39fc454b16410070e922c..b423218cc4f82e2f3e4b6f5f67a377d9f2f82a48 100644 (file)
@@ -201,13 +201,13 @@ profile =
 {
     rules =
     {
-        count = 25,
+        count = 0,
         sort = 'avg_ticks',
         file = { append = true }
     },
     modules =
     {
-        --count = 10,
+        count = 0,
         sort = 'avg_ticks',
         file = { append = true }
     }
@@ -498,6 +498,7 @@ stream_udp =
 ---------------------------------------------------------------------------
 
 -- alerts + packets
+--[[
 unified2 =
 {
     file = 'u2.log',
@@ -506,16 +507,17 @@ unified2 =
     mpls_event_types = true,
     vlan_event_types = true
 }
+--]]
 
 -- text
 --alert_syslog = { mode = 'LOG_AUTH LOG_ALERT' }
-alert_fast = { }
-alert_full = { }
---alert_test = { file = 'alert.tsv', session = false, msg = true }
+--alert_fast = { }
+--alert_full = { }
+--alert_test = { file = 'alert.tsv' }
 --alert_csv = { file = 'alert.csv' }
 
 -- pcap
-log_tcpdump = { file = 'snort++.pcap' }
+--log_tcpdump = { file = 'snort++.pcap' }
 
 ---------------------------------------------------------------------------
 -- ips rules and filters
@@ -550,6 +552,13 @@ default_rules =
 #alert http ( sid:1; msg:"1"; content:"HTTP"; )
 #alert http any -> 1.2.3.4 ( sid:2; msg:"2"; content:"HTTP"; )
 #alert http any any -> 1.2.3.4 80 ( sid:3; msg:"3"; content:"HTTP"; )
+
+#alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"BLACKLIST User-Agent known malicious    user agent - SAH Agent"; flow:to_server,established; content:"User-Agent|3A| SAH Agent"; metadata: policy balanced-ips drop, policy connectivity-ips drop, policy security-ips drop, service http;    classtype:misc-activity; sid:5808; rev:9;)
+
+#alert tcp any any -> any 80 ( msg:"Sample rule for Snort++"; http_uri; content:"attack"; sid:1; )
+#alert tcp any 80 -> any any ( msg:"Sample rule for Snort++"; http_header:Transfer-Encoding; content:"chunk"; sid:2; )
+#alert tcp any 80 -> any any ( msg:"Sample rule for Snort++"; http_header; content:"chunk"; sid:3; )
+#alert tcp any any -> any any ( msg:"Sample rule for Snort++"; content:"trigger"; sid:2; )
 ]]
 
 network =
@@ -560,8 +569,9 @@ network =
 -- put classic rules and includes in the include file and/or rules string
 ips =
 {
-    --include = '../active.rules',
-    --rules = default_rules,
+    --include = '../test.rules',
+    --include = 'active.rules',
+    rules = default_rules,
     enable_builtin_rules = false
 }
 
index 3f5c3c0d1584969fcf0fcfef3d0fb6ab23f9262c..981144ba09d1e0112c0c835bfaa3741bbb9b0bc9 100644 (file)
@@ -15,6 +15,7 @@ SET( PLUGIN_LIST
     ips_fragbits.cc
     ips_fragoffset.cc
     ips_http.cc
+    ips_http_header.cc
     ips_icmp_id.cc
     ips_icmp_seq.cc
     ips_icode.cc
index d7b19ed295554249f79132038145a758974434fc..bbe1ec23d6f33bae47f95078fb73194cefcdf07a 100644 (file)
@@ -16,6 +16,7 @@ ips_flags.cc \
 ips_fragbits.cc \
 ips_fragoffset.cc \
 ips_http.cc \
+ips_http_header.cc \
 ips_icmp_id.cc \
 ips_icmp_seq.cc \
 ips_icode.cc \
index 6b07f330c200f67bc01320713abc02706743f00a..5f1a3c176274c85ce68dad093122d090282e19d5 100644 (file)
@@ -18,6 +18,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
+// ips_http.cc author Russ Combs <rucombs@cisco.com>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -156,46 +157,6 @@ static const IpsApi uri_api =
     nullptr
 };
 
-//-------------------------------------------------------------------------
-// http_header
-//-------------------------------------------------------------------------
-
-#undef IPS_OPT
-#define IPS_OPT "http_header"
-
-static THREAD_LOCAL ProfileStats header_ps;
-
-static Module* header_mod_ctor()
-{
-    return new HttpCursorModule(IPS_OPT, header_ps);
-}
-
-static IpsOption* header_opt_ctor(Module*, OptTreeNode*)
-{
-    return new HttpIpsOption(IPS_OPT, header_ps, CAT_SET_HEADER);
-}
-
-static const IpsApi header_api =
-{
-    {
-        PT_IPS_OPTION,
-        IPS_OPT,
-        IPSAPI_PLUGIN_V0,
-        0,
-        header_mod_ctor,
-        mod_dtor
-    },
-    OPT_TYPE_DETECTION,
-    1, PROTO_BIT__TCP,
-    nullptr,
-    nullptr,
-    nullptr,
-    nullptr,
-    header_opt_ctor,
-    opt_dtor,
-    nullptr
-};
-
 //-------------------------------------------------------------------------
 // http_client_body
 //-------------------------------------------------------------------------
@@ -524,7 +485,6 @@ static const IpsApi raw_cookie_api =
 SO_PUBLIC const BaseApi* snort_plugins[] =
 {
     &uri_api.base,
-    &header_api.base,
     &client_body_api.base,
     &method_api.base,
     &cookie_api.base,
@@ -537,7 +497,6 @@ SO_PUBLIC const BaseApi* snort_plugins[] =
 };
 #else
 const BaseApi* ips_http_uri = &uri_api.base;
-const BaseApi* ips_http_header = &header_api.base;
 const BaseApi* ips_http_client_body = &client_body_api.base;
 const BaseApi* ips_http_method = &method_api.base;
 const BaseApi* ips_http_cookie = &cookie_api.base;
diff --git a/src/ips_options/ips_http_header.cc b/src/ips_options/ips_http_header.cc
new file mode 100644 (file)
index 0000000..33b13ce
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+** Copyright (C) 2002-2013 Sourcefire, Inc.
+** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation.  You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** 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
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+// ips_http_header.cc author Russ Combs <rucombs@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <string>
+using namespace std;
+
+#include "snort_types.h"
+#include "treenodes.h"
+#include "protocols/packet.h"
+#include "parser.h"
+#include "util.h"
+#include "snort_debug.h"
+#include "snort.h"
+#include "profiler.h"
+#include "flow/flow.h"
+#include "detection/detection_defines.h"
+#include "framework/ips_option.h"
+#include "framework/cursor.h"
+#include "framework/inspector.h"
+#include "framework/module.h"
+
+static const char* s_name = "http_header";
+
+static THREAD_LOCAL ProfileStats httpHeaderPerfStats;
+
+static const Parameter hh_params[] =
+{
+    { "*name", Parameter::PT_STRING, nullptr, nullptr,
+      "restrict to given header" },
+
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+//-------------------------------------------------------------------------
+// module
+//-------------------------------------------------------------------------
+
+class HttpHeaderModule : public Module
+{
+public:
+    HttpHeaderModule() : Module(s_name, hh_params) { };
+
+    bool begin(const char*, int, SnortConfig*);
+    bool set(const char*, Value&, SnortConfig*);
+
+    ProfileStats* get_profile() const
+    { return &httpHeaderPerfStats; };
+
+public:
+    string name;
+};
+
+bool HttpHeaderModule::begin(const char*, int, SnortConfig*)
+{
+    name.clear();
+    return true;
+}
+
+bool HttpHeaderModule::set(const char*, Value& v, SnortConfig*)
+{
+    if ( v.is("*name") )
+        name = v.get_string();
+
+    else
+        return false;
+
+    return true;
+}
+
+//-------------------------------------------------------------------------
+// generic header getter
+//-------------------------------------------------------------------------
+
+class HttpHeaderOption : public IpsOption
+{
+public:
+    HttpHeaderOption(string& s) : IpsOption(s_name)
+    { name = s; };
+
+    CursorActionType get_cursor_type() const
+    { return CAT_SET_OTHER; };
+
+    int eval(Cursor&, Packet*);
+
+private:
+    string name;
+};
+
+static bool find(
+    const string& s, const InspectionBuffer& b, Cursor& c)
+{
+    const char* h = s.c_str();
+    unsigned k = s.size();
+
+    const uint8_t* t = b.data;
+    unsigned n = b.len;
+
+    // find the start of header
+    do
+    {
+        if ( n < k )
+            return false;
+
+        if ( !strncasecmp(h, (char*)t, k) )
+            break;
+
+        t = (uint8_t*)memchr(t, '\n', n);
+
+        if ( !t )
+            return false;
+
+        n = b.len - (++t - b.data);
+    }
+    while ( true );
+
+    // now find the end of header
+    const uint8_t* z = (uint8_t*)memchr(t, '\n', n);
+
+    if ( z )
+    {
+        while ( isspace(z[-1]) && (z > t) )
+            --z;
+        n = z - t;
+    }
+    c.set(h, t, n);
+    return true;
+}
+
+int HttpHeaderOption::eval(Cursor& c, Packet* p)
+{
+    PROFILE_VARS;
+    MODULE_PROFILE_START(httpHeaderPerfStats);
+
+    int rval;
+    InspectionBuffer hb;
+
+    if ( !p->flow || !p->flow->gadget )
+        rval = DETECTION_OPTION_NO_MATCH;
+
+    // FIXIT cache id at parse time for runtime use
+    else if ( !p->flow->gadget->get_buf(s_name, p, hb) )
+        rval = DETECTION_OPTION_NO_MATCH;
+
+    else if ( !name.size() )
+    {
+        c.set(s_name, hb.data, hb.len);
+        rval = DETECTION_OPTION_MATCH;
+    }
+    else if ( find(name, hb, c) )
+        rval = DETECTION_OPTION_MATCH;
+
+    else
+        rval = DETECTION_OPTION_NO_MATCH;
+
+    MODULE_PROFILE_END(httpHeaderPerfStats);
+    return rval;
+}
+
+//-------------------------------------------------------------------------
+// api
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{
+    return new HttpHeaderModule;
+}
+
+static void mod_dtor(Module* m)
+{
+    delete m;
+}
+
+static IpsOption* hh_ctor(Module* m, OptTreeNode*)
+{
+    HttpHeaderModule* mod = (HttpHeaderModule*)m;
+    return new HttpHeaderOption(mod->name);
+}
+
+static void hh_dtor(IpsOption* p)
+{
+    delete p;
+}
+
+static const IpsApi header_api =
+{
+    {
+        PT_IPS_OPTION,
+        s_name,
+        IPSAPI_PLUGIN_V0,
+        0,
+        mod_ctor,
+        mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    1, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    hh_ctor,
+    hh_dtor,
+    nullptr
+};
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+    &header_api.base,
+    nullptr
+};
+#else
+const BaseApi* ips_http_header = &header_api.base;
+#endif
+