From: Mike Stepanek (mstepane) Date: Wed, 9 Sep 2020 21:20:07 +0000 (+0000) Subject: Merge pull request #2445 in SNORT/snort3 from ~THOPETER/snort3:lit_script to master X-Git-Tag: 3.0.2-6~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=978ead3b5fde58d2457e73aca8a20f02b2458bdb;p=thirdparty%2Fsnort3.git Merge pull request #2445 in SNORT/snort3 from ~THOPETER/snort3:lit_script to master Squashed commit of the following: commit 4f9f4879a38c0b385d012088b0fc05b9b2909fc0 Author: russ Date: Wed Aug 26 20:31:17 2020 -0400 http_inspect: support hyperscan literal search for accelerated blocking --- diff --git a/src/helpers/literal_search.cc b/src/helpers/literal_search.cc index 4f245ce2e..fb5df2504 100644 --- a/src/helpers/literal_search.cc +++ b/src/helpers/literal_search.cc @@ -56,13 +56,14 @@ void LiteralSearch::cleanup(LiteralSearch::Handle* h) } LiteralSearch* LiteralSearch::instantiate( - LiteralSearch::Handle* h, const uint8_t* pattern, unsigned pattern_len, bool no_case) + LiteralSearch::Handle* h, const uint8_t* pattern, unsigned pattern_len, bool no_case, bool hs) { #ifdef HAVE_HYPERSCAN - if ( SnortConfig::get_conf()->hyperscan_literals ) + if ( hs or SnortConfig::get_conf()->hyperscan_literals ) return new HyperSearch(h, pattern, pattern_len, no_case); #else UNUSED(h); + UNUSED(hs); #endif if ( no_case ) return new snort::BoyerMooreSearchNoCase(pattern, pattern_len); diff --git a/src/helpers/literal_search.h b/src/helpers/literal_search.h index 1dc4c8886..4d285ebf2 100644 --- a/src/helpers/literal_search.h +++ b/src/helpers/literal_search.h @@ -36,7 +36,8 @@ public: static Handle* setup(); // call from module ctor static void cleanup(Handle*); // call from module dtor - static LiteralSearch* instantiate(Handle*, const uint8_t* pattern, unsigned pattern_len, bool no_case = false); + static LiteralSearch* instantiate( + Handle*, const uint8_t* pattern, unsigned pattern_len, bool no_case = false, bool hs = false); virtual ~LiteralSearch() { } virtual int search(Handle*, const uint8_t* buffer, unsigned buffer_len) const = 0; diff --git a/src/service_inspectors/http_inspect/http_cutter.cc b/src/service_inspectors/http_inspect/http_cutter.cc index c30854dff..a173b21f2 100644 --- a/src/service_inspectors/http_inspect/http_cutter.cc +++ b/src/service_inspectors/http_inspect/http_cutter.cc @@ -25,6 +25,7 @@ #include "http_common.h" #include "http_enum.h" +#include "http_module.h" using namespace HttpEnums; @@ -285,12 +286,14 @@ HttpBodyCutter::HttpBodyCutter(AcceleratedBlocking accelerated_blocking_, Compre match_string = detain_string; match_string_upper = detain_upper; string_length = sizeof(detain_string); + HttpModule::get_detain_finder(finder, handle); } else { match_string = inspect_string; match_string_upper = inspect_upper; string_length = sizeof(inspect_string); + HttpModule::get_script_finder(finder, handle); } } } @@ -818,6 +821,30 @@ bool HttpBodyCutter::need_accelerated_blocking(const uint8_t* data, uint32_t len return false; } +bool HttpBodyCutter::find_partial(const uint8_t* input_buf, uint32_t input_length, bool end) +{ + for (uint32_t k = 0; k < input_length; k++) + { + // partial_match is persistent, enabling matches that cross data boundaries + if ((input_buf[k] == match_string[partial_match]) || + (input_buf[k] == match_string_upper[partial_match])) + { + if (++partial_match == string_length) + { + partial_match = 0; + return true; + } + } + else + { + partial_match = 0; + if ( end ) + return false; + } + } + return false; +} + // Currently we do accelerated blocking when we see a javascript bool HttpBodyCutter::dangerous(const uint8_t* data, uint32_t length) { @@ -856,25 +883,24 @@ bool HttpBodyCutter::dangerous(const uint8_t* data, uint32_t length) input_length = decomp_buffer_size - compress_stream->avail_out; } - for (uint32_t k = 0; k < input_length; k++) + std::unique_ptr uniq(decomp_output); + + if ( input_length > string_length ) { - // partial_match is persistent, enabling matches that cross data boundaries - if ((input_buf[k] == match_string[partial_match]) || - (input_buf[k] == match_string_upper[partial_match])) - { - if (++partial_match == string_length) - { - partial_match = 0; - delete[] decomp_output; - return true; - } - } - else - { - partial_match = 0; - } + if ( partial_match and find_partial(input_buf, input_length, true) ) + return true; + + if ( finder->search(handle, input_buf, input_length) >= 0 ) + return true; + + uint32_t delta = input_length - string_length + 1; + input_buf += delta; + input_length -= delta; } - delete[] decomp_output; + + if ( find_partial(input_buf, input_length, false) ) + return true; + return false; } diff --git a/src/service_inspectors/http_inspect/http_cutter.h b/src/service_inspectors/http_inspect/http_cutter.h index f512f860d..7d55b9353 100644 --- a/src/service_inspectors/http_inspect/http_cutter.h +++ b/src/service_inspectors/http_inspect/http_cutter.h @@ -23,6 +23,8 @@ #include #include +#include "helpers/literal_search.h" + #include "http_enum.h" #include "http_event.h" @@ -110,6 +112,7 @@ protected: private: bool dangerous(const uint8_t* data, uint32_t length); + bool find_partial(const uint8_t*, uint32_t, bool); const HttpEnums::AcceleratedBlocking accelerated_blocking; bool packet_detained = false; @@ -118,6 +121,8 @@ private: HttpEnums::CompressId compression; z_stream* compress_stream = nullptr; bool decompress_failed = false; + snort::LiteralSearch* finder = nullptr; + snort::LiteralSearch::Handle* handle = nullptr; const uint8_t* match_string; const uint8_t* match_string_upper; uint8_t string_length; diff --git a/src/service_inspectors/http_inspect/http_module.cc b/src/service_inspectors/http_inspect/http_module.cc index 4746276e8..af6016b68 100644 --- a/src/service_inspectors/http_inspect/http_module.cc +++ b/src/service_inspectors/http_inspect/http_module.cc @@ -23,6 +23,7 @@ #include "http_module.h" +#include "helpers/literal_search.h" #include "log/messages.h" #include "http_enum.h" @@ -32,6 +33,37 @@ using namespace snort; using namespace HttpEnums; +LiteralSearch::Handle* s_handle = nullptr; +LiteralSearch* s_detain = nullptr; +LiteralSearch* s_script = nullptr; + +HttpModule::HttpModule() : Module(HTTP_NAME, HTTP_HELP, http_params) +{ + s_handle = LiteralSearch::setup(); + s_detain = LiteralSearch::instantiate(s_handle, (const uint8_t*)"", 9, true, true); +} + +HttpModule::~HttpModule() +{ + delete params; + delete s_detain; + delete s_script; + LiteralSearch::cleanup(s_handle); +} + +void HttpModule::get_detain_finder(LiteralSearch*& finder, LiteralSearch::Handle*& handle) +{ + finder = s_detain; + handle = s_handle; +} + +void HttpModule::get_script_finder(LiteralSearch*& finder, LiteralSearch::Handle*& handle) +{ + finder = s_script; + handle = s_handle; +} + const Parameter HttpModule::http_params[] = { { "request_depth", Parameter::PT_INT, "-1:max53", "-1", diff --git a/src/service_inspectors/http_inspect/http_module.h b/src/service_inspectors/http_inspect/http_module.h index e81e6aa97..24d4834ff 100644 --- a/src/service_inspectors/http_inspect/http_module.h +++ b/src/service_inspectors/http_inspect/http_module.h @@ -24,6 +24,7 @@ #include #include "framework/module.h" +#include "helpers/literal_search.h" #include "profiler/profiler.h" #include "http_enum.h" @@ -95,8 +96,8 @@ public: class HttpModule : public snort::Module { public: - HttpModule() : Module(HTTP_NAME, HTTP_HELP, http_params) { } - ~HttpModule() override { delete params; } + HttpModule(); + ~HttpModule() override; bool begin(const char*, int, snort::SnortConfig*) override; bool end(const char*, int, snort::SnortConfig*) override; bool set(const char*, snort::Value&, snort::SnortConfig*) override; @@ -118,6 +119,9 @@ public: static PegCount get_peg_counts(HttpEnums::PEG_COUNT counter) { return peg_counts[counter]; } + static void get_detain_finder(snort::LiteralSearch*&, snort::LiteralSearch::Handle*&); + static void get_script_finder(snort::LiteralSearch*&, snort::LiteralSearch::Handle*&); + snort::ProfileStats* get_profile() const override; static snort::ProfileStats& get_profile_stats() diff --git a/src/service_inspectors/http_inspect/test/http_module_test.cc b/src/service_inspectors/http_inspect/test/http_module_test.cc index f5f1e86ce..03667238c 100644 --- a/src/service_inspectors/http_inspect/test/http_module_test.cc +++ b/src/service_inspectors/http_inspect/test/http_module_test.cc @@ -23,6 +23,7 @@ #include "config.h" #endif +#include "helpers/literal_search.h" #include "log/messages.h" #include "service_inspectors/http_inspect/http_js_norm.h" @@ -45,6 +46,10 @@ void ParseError(const char*, ...) {} void Value::get_bits(std::bitset<256ul>&) const {} int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; } +LiteralSearch::Handle* LiteralSearch::setup() { return nullptr; } +void LiteralSearch::cleanup(LiteralSearch::Handle*) {} +LiteralSearch* LiteralSearch::instantiate(LiteralSearch::Handle*, const uint8_t*, unsigned, bool, + bool) { return nullptr; } } void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { } diff --git a/src/service_inspectors/http_inspect/test/http_uri_norm_test.cc b/src/service_inspectors/http_inspect/test/http_uri_norm_test.cc index 5d095a146..c1db2a57e 100644 --- a/src/service_inspectors/http_inspect/test/http_uri_norm_test.cc +++ b/src/service_inspectors/http_inspect/test/http_uri_norm_test.cc @@ -23,7 +23,9 @@ #include "config.h" #endif +#include "helpers/literal_search.h" #include "log/messages.h" + #include "service_inspectors/http_inspect/http_js_norm.h" #include "service_inspectors/http_inspect/http_uri_norm.h" @@ -40,6 +42,10 @@ void ParseWarning(WarningGroup, const char*, ...) {} void ParseError(const char*, ...) {} void Value::get_bits(std::bitset<256ul>&) const {} int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; } +LiteralSearch::Handle* LiteralSearch::setup() { return nullptr; } +void LiteralSearch::cleanup(LiteralSearch::Handle*) {} +LiteralSearch* LiteralSearch::instantiate(LiteralSearch::Handle*, const uint8_t*, unsigned, bool, + bool) { return nullptr; } } void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }