Jan 06 2026 dev (#387)

* sync code

* update code to support brotli

* update code to support brotli

* update code to support brotli

* sync code

* fix findBrotli

* sync code

* sync code

* sync code

* sync code

---------

Co-authored-by: Ned Wright <nedwright@proton.me>
Co-authored-by: Daniel Eisenberg <danielei@checkpoint.com>
This commit is contained in:
Daniel-Eisenberg
2026-01-13 17:17:52 +02:00
committed by GitHub
parent c1058db57d
commit e7b6e51b31
216 changed files with 12601 additions and 2825 deletions

View File

@@ -21,13 +21,13 @@
#include <vector>
#include "config.h"
#include "i_generic_rulebase.h"
#include "i_first_tier_agg.h"
#include "ips_entry.h"
#include "ips_enums.h"
#include "log_generator.h"
#include "parsed_context.h"
#include "pm_hook.h"
#include "i_generic_rulebase.h"
#define DEFAULT_IPS_YIELD_COUNT 500
@@ -402,6 +402,7 @@ public:
LogTriggerConf getTrigger() const;
std::set<ParameterBehavior>
getBehavior(const std::unordered_map<std::string, std::set<std::string>> &exceptions_dict) const;
@@ -410,10 +411,21 @@ private:
/// \param ips_state The IPS entry.
ActionResults getAction(const IPSEntry &ips_state) const;
void sendLog(
const Buffer &context_buffer,
const IPSEntry &ips_state,
const std::tuple<
IPSSignatureSubTypes::SignatureAction,
std::string, std::vector<std::string>
> &override_action,
bool is_prevent
) const;
std::shared_ptr<CompleteSignature> signature;
SignatureAction action;
std::string trigger_id;
std::string exception_id;
mutable bool bSupressLog = false;
};
} // namespace IPSSignatureSubTypes

View File

@@ -13,7 +13,7 @@
#include "virtual_modifiers.h"
#include "helper.h"
#include "ips_common_types.h"
#include "nginx_attachment_common.h"
#include "nano_attachment_common.h"
using namespace std;
@@ -46,9 +46,9 @@ class IPSComp::Impl
public Listener<HttpResponseBodyEvent>,
public Listener<EndTransactionEvent>
{
static constexpr auto DROP = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP;
static constexpr auto ACCEPT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT;
static constexpr auto INSPECT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
static constexpr auto DROP = ServiceVerdict::TRAFFIC_VERDICT_DROP;
static constexpr auto ACCEPT = ServiceVerdict::TRAFFIC_VERDICT_ACCEPT;
static constexpr auto INSPECT = ServiceVerdict::TRAFFIC_VERDICT_INSPECT;
class SigsFirstTierAgg
{
@@ -383,8 +383,8 @@ IPSComp::preload()
registerExpectedResource<SnortSignaturesResource>("IPSSnortSigs", "protections");
registerExpectedConfiguration<IPSConfiguration>("IPS", "IpsConfigurations");
registerExpectedConfiguration<uint>("IPS", "Max Field Size");
registerExpectedConfiguration<IPSSignatures>("IPS", "IpsProtections");
registerExpectedConfiguration<SnortSignatures>("IPSSnortSigs", "SnortProtections");
registerExpectedConfigurationWithCache<IPSSignatures>("assetId", "IPS", "IpsProtections");
registerExpectedConfigurationWithCache<SnortSignatures>("assetId", "IPSSnortSigs", "SnortProtections");
registerExpectedConfigFile("ips", Config::ConfigFileType::Policy);
registerExpectedConfigFile("ips", Config::ConfigFileType::Data);
registerExpectedConfigFile("snort", Config::ConfigFileType::Policy);

View File

@@ -321,6 +321,9 @@ SignatureAndAction::getAction(const IPSEntry &ips_state) const
override_actions.insert(behavior.getValue());
const string &override_id = behavior.getId();
if (!override_id.empty()) override_ids.push_back(override_id);
} else if(behavior.getKey() == BehaviorKey::LOG && behavior.getValue() == BehaviorValue::IGNORE) {
dbgTrace(D_IPS) << "setting bSupressLog due to override behavior: " << behavior.getId();
bSupressLog = true;
}
}
@@ -358,8 +361,10 @@ set<ParameterBehavior>
SignatureAndAction::getBehavior(const unordered_map<string, set<string>> &exceptions_dict) const
{
I_GenericRulebase *i_rulebase = Singleton::Consume<I_GenericRulebase>::by<IPSComp>();
if (exception_id.empty()) return i_rulebase->getBehavior(exceptions_dict);
if (exception_id.empty()) {
dbgTrace(D_RULEBASE_CONFIG) << "No exception id provided, using default behavior";
return i_rulebase->getBehavior(exceptions_dict);
}
return i_rulebase->getParameterException(exception_id).getBehavior(exceptions_dict);
}
@@ -453,10 +458,25 @@ SignatureAndAction::isMatchedPrevent(const Buffer &context_buffer, const set<PMP
return false;
}
dbgDebug(D_IPS) << "Signature matched - sending log";
bool is_prevent = get<0>(override_action) == IPSSignatureSubTypes::SignatureAction::PREVENT;
if(bSupressLog) {
dbgTrace(D_IPS) << "Signature matched - not sending log due to exception behavior";
} else {
sendLog(context_buffer, ips_state, override_action, is_prevent);
}
return is_prevent;
}
void SignatureAndAction::sendLog(
const Buffer &context_buffer,
const IPSEntry &ips_state,
const tuple<IPSSignatureSubTypes::SignatureAction, string, vector<string>> &override_action,
bool is_prevent
) const
{
dbgFlow(D_IPS) << "Signature matched - sending log";
auto trigger = getTrigger();
bool is_prevent = get<0>(override_action) == IPSSignatureSubTypes::SignatureAction::PREVENT;
auto severity = signature->getSeverity() < IPSLevel::HIGH ? Severity::HIGH : Severity::CRITICAL;
if (get<0>(override_action) == IPSSignatureSubTypes::SignatureAction::DETECT) severity = Severity::INFO;
@@ -560,7 +580,7 @@ SignatureAndAction::isMatchedPrevent(const Buffer &context_buffer, const set<PMP
uint res_size = res_body.ok() && trigger.isWebLogFieldActive(::res_body) ? res_body.unpack().size() : 0;
if (req_size + res_size > max_size) {
if (req_size + 500 > max_size) {
res_size = std::min(500u, res_size);
res_size = min(500u, res_size);
req_size = max_size - res_size;
} else {
res_size = max_size - req_size;
@@ -572,10 +592,8 @@ SignatureAndAction::isMatchedPrevent(const Buffer &context_buffer, const set<PMP
log << LogField("waapOverride", get<1>(override_action));
if (!get<2>(override_action).empty()) log.addToOrigin(LogField("exceptionIdList", get<2>(override_action)));
log << LogField("securityAction", is_prevent ? "Prevent" : "Detect");
return is_prevent;
log << LogField("securityAction", is_prevent ? "Prevent" : "Detect");
}
void

View File

@@ -109,11 +109,11 @@ operator ==(const EventVerdict &first, const EventVerdict &second)
return first.getVerdict() == second.getVerdict();
}
const EventVerdict ComponentTest::inspect(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT);
const EventVerdict ComponentTest::inspect(ServiceVerdict::TRAFFIC_VERDICT_INSPECT);
const EventVerdict ComponentTest::accept(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT);
const EventVerdict ComponentTest::accept(ServiceVerdict::TRAFFIC_VERDICT_ACCEPT);
const EventVerdict ComponentTest::drop(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP);
const EventVerdict ComponentTest::drop(ServiceVerdict::TRAFFIC_VERDICT_DROP);
TEST_F(ComponentTest, check_init_fini_do_not_crush)
{

View File

@@ -19,6 +19,7 @@
#include "generic_rulebase/generic_rulebase_context.h"
#include "encryptor.h"
#include "mock/mock_table.h"
USE_DEBUG_FLAG(D_IPS);
using namespace testing;
using namespace std;
@@ -194,6 +195,101 @@ public:
gen_ctx->activate();
}
// Loads an exception with log: ignore behavior, as in the provided JSON
void loadExceptionsIgnoreLog()
{
BasicRuleConfig::preload();
registerExpectedConfiguration<ParameterException>("rulebase", "exception");
string test_config(
"{"
" \"rulebase\": {"
" \"rulesConfig\": ["
" {"
" \"context\": \"All()\","
" \"priority\": 1,"
" \"ruleId\": \"5eaef0726765c30010bae8bb\","
" \"ruleName\": \"Acme web API\","
" \"assetId\": \"5e243effd858007660b758ad\","
" \"assetName\": \"Acme Power API\","
" \"parameters\": ["
" {"
" \"parameterId\": \"6c3867be-4da5-42c2-93dc-8f509a764003\","
" \"parameterType\": \"exceptions\","
" \"parameterName\": \"exception\""
" }"
" ],"
" \"zoneId\": \"\","
" \"zoneName\": \"\""
" }"
" ],"
" \"exception\": ["
" {"
" \"context\": \"Any(parameterId(6c3867be-4da5-42c2-93dc-8f509a764003))\","
" \"exceptions\": ["
" {"
" \"match\": {"
" \"type\": \"operator\","
" \"op\": \"and\","
" \"items\": ["
" {"
" \"type\": \"condition\","
" \"op\": \"equals\","
" \"key\": \"sourceIdentifier\","
" \"value\": [\"1.1.1.1\"]"
" }"
" ]"
" },"
" \"behavior\": {"
" \"key\": \"log\","
" \"value\": \"ignore\""
" }"
" },"
" {"
" \"match\": {"
" \"type\": \"operator\","
" \"op\": \"or\","
" \"items\": ["
" {"
" \"type\": \"condition\","
" \"op\": \"equals\","
" \"key\": \"protectionName\","
" \"value\": [\"Test1\"]"
" },"
" {"
" \"type\": \"condition\","
" \"op\": \"equals\","
" \"key\": \"protectionName\","
" \"value\": [\"Test2\"]"
" },"
" {"
" \"type\": \"condition\","
" \"op\": \"equals\","
" \"key\": \"sourceIdentifier\","
" \"value\": [\"1.1.1.1\"]"
" }"
" ]"
" },"
" \"behavior\": {"
" \"key\": \"action\","
" \"value\": \"accept\""
" }"
" }"
" ]"
" }"
" ]"
" }"
"}"
);
istringstream ss(test_config);
auto i_config = Singleton::Consume<Config::I_Config>::from(config);
i_config->loadConfiguration(ss);
gen_ctx = make_unique<GenericRulebaseContext>();
gen_ctx->activate();
}
void
load(const IPSSignaturesResource &policy, const string &severity, const string &confidence)
{
@@ -261,6 +357,7 @@ public:
IPSSignaturesResource performance_signatures3;
IPSSignaturesResource single_broken_signature;
NiceMock<MockTable> table;
NiceMock<MockLogging> logs;
MockAgg mock_agg;
private:
@@ -273,7 +370,6 @@ private:
ConfigComponent config;
Encryptor encryptor;
AgentDetails details;
StrictMock<MockLogging> logs;
IPSEntry ips_state;
string signature1 =
@@ -524,6 +620,23 @@ TEST_F(SignatureTest, basic_load_of_signatures)
EXPECT_FALSE(sigs.isEmpty("HTTP_REQUEST_BODY"));
}
TEST_F(SignatureTest, ignore_exception_suppresses_log)
{
load(single_signature2, "Low or above", "Low");
loadExceptionsIgnoreLog();
expectLog("\"protectionId\": \"Test3\"", "\"eventSeverity\": \"Critical\"");
EXPECT_TRUE(checkData("gggddd"));
ScopedContext ctx;
ctx.registerValue<string>("sourceIdentifiers", "1.1.1.1");
// No log should be sent when the exception matches
EXPECT_CALL(logs, sendLog(_)).Times(0);
EXPECT_FALSE(checkData("gggddd"));
}
TEST_F(SignatureTest, single_signature_matching_override)
{
load(single_signature, "Low or above", "Low");