mirror of
https://github.com/openappsec/openappsec.git
synced 2025-12-31 13:49:08 +03:00
Mar 21st 2024 update
This commit is contained in:
@@ -12,20 +12,34 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "access_control_practice.h"
|
||||
#include "new_practice.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
static const map<string, string> valid_modes_to_key = {
|
||||
static const set<string> valid_modes = {
|
||||
"prevent",
|
||||
"detect",
|
||||
"inactive",
|
||||
"prevent-learn",
|
||||
"detect-learn",
|
||||
"as-top-level",
|
||||
"inherited"
|
||||
};
|
||||
|
||||
static const unordered_map<string, string> valid_modes_to_key = {
|
||||
{"prevent", "Active"},
|
||||
{"prevent-learn", "Active"},
|
||||
{"detect", "Detect"},
|
||||
{"detect-learn", "Detect"},
|
||||
{"inactive", "Inactive"}
|
||||
};
|
||||
|
||||
static const set<string> valid_units = {"minute", "second"};
|
||||
|
||||
static const std::unordered_map<std::string, std::string> key_to_units_val = {
|
||||
static const unordered_map<std::string, std::string> key_to_units_val = {
|
||||
{ "second", "Second"},
|
||||
{ "minute", "Minute"}
|
||||
};
|
||||
@@ -177,13 +191,10 @@ void
|
||||
AccessControlRateLimit::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Access control rate limit";
|
||||
string in_mode;
|
||||
parseAppsecJSONKey<string>("overrideMode", in_mode, archive_in, "detect");
|
||||
if (valid_modes_to_key.find(in_mode) == valid_modes_to_key.end()) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec access control rate limit override mode invalid: " << in_mode;
|
||||
throw PolicyGenException("AppSec access control rate limit override mode invalid: " + in_mode);
|
||||
} else {
|
||||
mode = valid_modes_to_key.at(in_mode);
|
||||
parseMandatoryAppsecJSONKey<string>("overrideMode", mode, archive_in, "inactive");
|
||||
if (valid_modes.find(mode) == valid_modes.end()) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec access control rate limit override mode invalid: " << mode;
|
||||
throw PolicyGenException("AppSec access control rate limit override mode invalid: " + mode);
|
||||
}
|
||||
parseAppsecJSONKey<std::vector<AccessControlRateLimiteRules>>("rules", rules, archive_in);
|
||||
}
|
||||
@@ -205,9 +216,10 @@ AccessControlRateLimit::getRules() const
|
||||
}
|
||||
|
||||
const string &
|
||||
AccessControlRateLimit::getMode() const
|
||||
AccessControlRateLimit::getMode(const std::string &default_mode) const
|
||||
{
|
||||
return mode;
|
||||
const string &res = getModeWithDefault(mode, default_mode, valid_modes_to_key);
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -227,7 +239,7 @@ AccessControlPracticeSpec::setName(const string &_name)
|
||||
}
|
||||
|
||||
const AccessControlRateLimit &
|
||||
AccessControlPracticeSpec::geRateLimit() const
|
||||
AccessControlPracticeSpec::getRateLimit() const
|
||||
{
|
||||
return rate_limit;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ AppSecPracticeWebAttacks::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice spec";
|
||||
parseAppsecJSONKey<AppSecWebAttackProtections>("protections", protections, archive_in);
|
||||
parseAppsecJSONKey<string>("override-mode", mode, archive_in, "Unset");
|
||||
parseAppsecJSONKey<string>("override-mode", mode, archive_in, "as-top-level");
|
||||
if (valid_modes.count(mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec practice override mode invalid: " << mode;
|
||||
}
|
||||
@@ -187,7 +187,7 @@ AppSecPracticeWebAttacks::getMinimumConfidence() const
|
||||
const string &
|
||||
AppSecPracticeWebAttacks::getMode(const string &default_mode) const
|
||||
{
|
||||
if (mode == "Unset" || (key_to_practices_val2.find(mode) == key_to_practices_val2.end())) {
|
||||
if (isModeInherited(mode) || (key_to_practices_val2.find(mode) == key_to_practices_val2.end())) {
|
||||
dbgError(D_LOCAL_POLICY) << "Couldn't find a value for key: " << mode << ". Returning " << default_mode;
|
||||
return default_mode;
|
||||
}
|
||||
@@ -429,6 +429,9 @@ WebAppSection::WebAppSection(
|
||||
context(_context),
|
||||
web_attack_mitigation_severity(parsed_appsec_spec.getWebAttacks().getMinimumConfidence()),
|
||||
web_attack_mitigation_mode(parsed_appsec_spec.getWebAttacks().getMode(default_mode)),
|
||||
csrf_protection_mode("Disabled"),
|
||||
open_redirect_mode("Disabled"),
|
||||
error_disclosure_mode("Disabled"),
|
||||
practice_advanced_config(parsed_appsec_spec),
|
||||
anti_bots(parsed_appsec_spec.getAntiBot()),
|
||||
trusted_sources({ parsed_trusted_sources })
|
||||
@@ -451,6 +454,7 @@ WebAppSection::WebAppSection(
|
||||
}
|
||||
}
|
||||
|
||||
// Used for V1Beta2
|
||||
WebAppSection::WebAppSection(
|
||||
const string &_application_urls,
|
||||
const string &_asset_id,
|
||||
@@ -465,7 +469,8 @@ WebAppSection::WebAppSection(
|
||||
const PracticeAdvancedConfig &_practice_advanced_config,
|
||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
const AppSecTrustedSources &parsed_trusted_sources)
|
||||
const AppSecTrustedSources &parsed_trusted_sources,
|
||||
const NewAppSecWebAttackProtections &protections)
|
||||
:
|
||||
application_urls(_application_urls),
|
||||
asset_id(_asset_id),
|
||||
@@ -489,6 +494,10 @@ WebAppSection::WebAppSection(
|
||||
web_attack_mitigation_severity == "medium" ? "high" :
|
||||
"Error";
|
||||
|
||||
csrf_protection_mode = protections.getCsrfProtectionMode(_web_attack_mitigation_mode);
|
||||
open_redirect_mode = protections.getOpenRedirectMode(_web_attack_mitigation_mode);
|
||||
error_disclosure_mode = protections.getErrorDisclosureMode(_web_attack_mitigation_mode);
|
||||
|
||||
triggers.push_back(TriggersInWaapSection(parsed_log_trigger));
|
||||
for (const SourcesIdentifiers &source_ident : parsed_trusted_sources.getSourcesIdentifiers()) {
|
||||
overrides.push_back(AppSecOverride(source_ident));
|
||||
@@ -510,9 +519,9 @@ WebAppSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
cereal::make_nvp("webAttackMitigationAction", web_attack_mitigation_action),
|
||||
cereal::make_nvp("webAttackMitigationMode", web_attack_mitigation_mode),
|
||||
cereal::make_nvp("practiceAdvancedConfig", practice_advanced_config),
|
||||
cereal::make_nvp("csrfProtection", disabled_str),
|
||||
cereal::make_nvp("openRedirect", disabled_str),
|
||||
cereal::make_nvp("errorDisclosure", disabled_str),
|
||||
cereal::make_nvp("csrfProtection", csrf_protection_mode),
|
||||
cereal::make_nvp("openRedirect", open_redirect_mode),
|
||||
cereal::make_nvp("errorDisclosure", error_disclosure_mode),
|
||||
cereal::make_nvp("practiceId", practice_id),
|
||||
cereal::make_nvp("practiceName", practice_name),
|
||||
cereal::make_nvp("assetId", asset_id),
|
||||
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::vector<AccessControlRateLimiteRules> & getRules() const;
|
||||
const std::string & getMode() const;
|
||||
const std::string & getMode(const std::string &default_mode = "inactive") const;
|
||||
std::vector<RateLimitRulesSection> createRateLimitRulesSection(const RateLimitRulesTriggerSection &trigger) const;
|
||||
|
||||
private:
|
||||
@@ -178,7 +178,7 @@ class AccessControlPracticeSpec
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const AccessControlRateLimit & geRateLimit() const;
|
||||
const AccessControlRateLimit &getRateLimit() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
const std::string & getName() const;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
@@ -278,6 +278,7 @@ public:
|
||||
const std::vector<InnerException> &parsed_exceptions
|
||||
);
|
||||
|
||||
// used for V1beta2
|
||||
WebAppSection(
|
||||
const std::string &_application_urls,
|
||||
const std::string &_asset_id,
|
||||
@@ -292,7 +293,8 @@ public:
|
||||
const PracticeAdvancedConfig &_practice_advanced_config,
|
||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
const AppSecTrustedSources &parsed_trusted_sources);
|
||||
const AppSecTrustedSources &parsed_trusted_sources,
|
||||
const NewAppSecWebAttackProtections &protections);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
@@ -310,6 +312,9 @@ private:
|
||||
std::string web_attack_mitigation_action;
|
||||
std::string web_attack_mitigation_severity;
|
||||
std::string web_attack_mitigation_mode;
|
||||
std::string csrf_protection_mode;
|
||||
std::string open_redirect_mode;
|
||||
std::string error_disclosure_mode;
|
||||
bool web_attack_mitigation;
|
||||
std::vector<TriggersInWaapSection> triggers;
|
||||
PracticeAdvancedConfig practice_advanced_config;
|
||||
|
||||
@@ -97,8 +97,7 @@ parseAppsecJSONKey(
|
||||
value = default_value;
|
||||
if (!mandatory) {
|
||||
dbgDebug(D_LOCAL_POLICY)
|
||||
<< "Could not parse the required key. Key: \""<< key_name
|
||||
<< "\", Error: " << e.what();
|
||||
<< "Could not parse a non-mandatory key: \""<< key_name << "\", Error: " << e.what();
|
||||
} else {
|
||||
throw PolicyGenException(
|
||||
"Could not parse a mandatory key: \"" + key_name + "\", Error: " + std::string(e.what())
|
||||
|
||||
@@ -24,6 +24,14 @@
|
||||
#include "debug.h"
|
||||
#include "local_policy_common.h"
|
||||
|
||||
bool isModeInherited(const std::string &mode);
|
||||
|
||||
const std::string &getModeWithDefault(
|
||||
const std::string &mode,
|
||||
const std::string &default_mode,
|
||||
const std::unordered_map<std::string, std::string> &key_to_val
|
||||
);
|
||||
|
||||
class IpsProtectionsRulesSection
|
||||
{
|
||||
public:
|
||||
@@ -126,8 +134,8 @@ class NewIntrusionPrevention
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
std::vector<IpsProtectionsRulesSection> createIpsRules() const;
|
||||
const std::string & getMode() const;
|
||||
std::vector<IpsProtectionsRulesSection> createIpsRules(const std::string &default_mode) const;
|
||||
const std::string & getMode(const std::string &default_mode = "inactive") const;
|
||||
|
||||
private:
|
||||
std::string override_mode;
|
||||
@@ -273,7 +281,8 @@ public:
|
||||
const std::string &asset_name,
|
||||
const std::string &asset_id,
|
||||
const std::string &practice_name,
|
||||
const std::string &practice_id
|
||||
const std::string &practice_id,
|
||||
const std::string &default_mode
|
||||
) const;
|
||||
|
||||
private:
|
||||
@@ -486,7 +495,7 @@ public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
void addFile(const std::string &file_name);
|
||||
const std::string & getOverrideMode() const;
|
||||
const std::string & getOverrideMode(const std::string &default_mode = "inactive") const;
|
||||
const std::vector<std::string> & getConfigMap() const;
|
||||
const std::vector<std::string> & getFiles() const;
|
||||
bool isTemporary() const;
|
||||
@@ -530,10 +539,10 @@ class NewAppSecWebAttackProtections
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string getCsrfProtectionMode() const;
|
||||
const std::string & getErrorDisclosureMode() const;
|
||||
const std::string & getCsrfProtectionMode(const std::string &default_mode = "inactive") const;
|
||||
const std::string & getErrorDisclosureMode(const std::string &default_mode = "inactive") const;
|
||||
const std::string & getOpenRedirectMode(const std::string &default_mode = "inactive") const;
|
||||
bool getNonValidHttpMethods() const;
|
||||
const std::string getOpenRedirectMode() const;
|
||||
|
||||
private:
|
||||
std::string csrf_protection;
|
||||
@@ -551,9 +560,9 @@ public:
|
||||
int getMaxHeaderSizeBytes() const;
|
||||
int getMaxObjectDepth() const;
|
||||
int getMaxUrlSizeBytes() const;
|
||||
const std::string & getMinimumConfidence() const;
|
||||
const NewAppSecWebAttackProtections & getprotections() const;
|
||||
const std::string & getMode(const std::string &default_mode = "Inactive") const;
|
||||
const std::string & getMinimumConfidence(const std::string &default_mode = "inactive") const;
|
||||
const NewAppSecWebAttackProtections & getProtections() const;
|
||||
const std::string & getMode(const std::string &default_mode = "inactive") const;
|
||||
|
||||
private:
|
||||
int max_body_size_kb;
|
||||
|
||||
@@ -158,7 +158,8 @@ private:
|
||||
const std::string &source_identifier,
|
||||
const std::string & context,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations,
|
||||
const std::string &default_mode
|
||||
);
|
||||
|
||||
void createSnortProtecionsSection(const std::string &file_name, bool is_temporary);
|
||||
@@ -172,7 +173,8 @@ private:
|
||||
const std::string &practice_id,
|
||||
const std::string &source_identifier,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations,
|
||||
const std::string &default_mode
|
||||
);
|
||||
|
||||
void
|
||||
@@ -183,7 +185,8 @@ private:
|
||||
const std::string &practice_name,
|
||||
const std::string & context,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations,
|
||||
const std::string &default_mode
|
||||
);
|
||||
|
||||
void
|
||||
@@ -192,6 +195,7 @@ private:
|
||||
const std::string &url,
|
||||
const std::string &uri,
|
||||
const std::string &trigger_id,
|
||||
const std::string &default_mode,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
);
|
||||
|
||||
@@ -414,7 +414,7 @@ K8sPolicyUtils::createAppsecPolicyK8sFromV1beta2Crds(
|
||||
|
||||
vector<AccessControlPracticeSpec> access_control_practices =
|
||||
extractV1Beta2ElementsFromCluster<AccessControlPracticeSpec>(
|
||||
"accesscontrolpractice",
|
||||
"accesscontrolpractices",
|
||||
policy_elements_names[AnnotationTypes::ACCESS_CONTROL_PRACTICE]
|
||||
);
|
||||
|
||||
@@ -489,6 +489,8 @@ K8sPolicyUtils::createAppsecPolicyK8s(const string &policy_name, const string &i
|
||||
!doesVersionExist(maybe_appsec_policy_spec.unpack().getMetaData().getAnnotations(), "v1beta1")
|
||||
) {
|
||||
try {
|
||||
std::string v1beta1_error =
|
||||
maybe_appsec_policy_spec.ok() ? "There is no v1beta1 policy" : maybe_appsec_policy_spec.getErr();
|
||||
dbgWarning(D_LOCAL_POLICY
|
||||
) << "Failed to retrieve Appsec policy with crds version: v1beta1, Trying version: v1beta2";
|
||||
auto maybe_v1beta2_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<NewAppsecPolicySpec>>(
|
||||
@@ -498,7 +500,7 @@ K8sPolicyUtils::createAppsecPolicyK8s(const string &policy_name, const string &i
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve AppSec policy. Error: " << maybe_v1beta2_appsec_policy_spec.getErr();
|
||||
return std::make_tuple(
|
||||
genError("Failed to retrieve AppSec v1beta1 policy. Error: " + maybe_appsec_policy_spec.getErr()),
|
||||
genError("Failed to retrieve AppSec v1beta1 policy. Error: " + v1beta1_error),
|
||||
genError(
|
||||
"Failed to retrieve AppSec v1beta2 policy. Error: " + maybe_v1beta2_appsec_policy_spec.getErr()
|
||||
)
|
||||
@@ -584,7 +586,9 @@ K8sPolicyUtils::createAppsecPoliciesFromIngresses()
|
||||
);
|
||||
if (!std::get<0>(maybe_appsec_policy).ok() && !std::get<1>(maybe_appsec_policy).ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to create appsec policy. Error: "
|
||||
<< "Failed to create appsec policy. v1beta1 Error: "
|
||||
<< std::get<0>(maybe_appsec_policy).getErr()
|
||||
<< ". v1beta2 Error: "
|
||||
<< std::get<1>(maybe_appsec_policy).getErr();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ V1beta2AppsecLinuxPolicy::serialize(cereal::JSONInputArchive &archive_in)
|
||||
archive_in
|
||||
);
|
||||
parseAppsecJSONKey<vector<NewAppsecLogTrigger>>("logTriggers", log_triggers, archive_in);
|
||||
parseAppsecJSONKey<vector<NewAppSecCustomResponse>>("customResponse", custom_responses, archive_in);
|
||||
parseAppsecJSONKey<vector<NewAppSecCustomResponse>>("customResponses", custom_responses, archive_in);
|
||||
parseAppsecJSONKey<vector<NewAppsecException>>("exceptions", exceptions, archive_in);
|
||||
parseAppsecJSONKey<vector<NewTrustedSourcesSpec>>("trustedSources", trusted_sources, archive_in);
|
||||
parseAppsecJSONKey<vector<NewSourcesIdentifiers>>("sourcesIdentifiers", sources_identifiers, archive_in);
|
||||
|
||||
@@ -44,7 +44,7 @@ void
|
||||
NewAppsecException::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading New AppSec exception";
|
||||
parseAppsecJSONKey<string>("name", name, archive_in, "exception");
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
parseMandatoryAppsecJSONKey<string>("action", action, archive_in, "accept");
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
if (valid_actions.count(action) == 0) {
|
||||
|
||||
@@ -21,8 +21,16 @@ USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
static const set<string> performance_impacts = {"low", "medium", "high"};
|
||||
static const set<string> severity_levels = {"low", "medium", "high", "critical"};
|
||||
static const set<string> size_unit = {"bytes", "KB", "MB", "GB"};
|
||||
static const set<string> confidences_actions = {"prevent", "detect", "inactive"};
|
||||
static const set<string> valid_modes = {"prevent", "detect", "inactive", "prevent-learn", "detect-learn"};
|
||||
static const set<string> confidences_actions = {"prevent", "detect", "inactive", "as-top-level", "inherited"};
|
||||
static const set<string> valid_modes = {
|
||||
"prevent",
|
||||
"detect",
|
||||
"inactive",
|
||||
"prevent-learn",
|
||||
"detect-learn",
|
||||
"as-top-level",
|
||||
"inherited"
|
||||
};
|
||||
static const set<string> valid_confidences = {"medium", "high", "critical"};
|
||||
static const std::unordered_map<std::string, std::string> key_to_performance_impact_val = {
|
||||
{ "low", "Low or lower"},
|
||||
@@ -48,6 +56,30 @@ static const std::unordered_map<std::string, uint64_t> unit_to_int = {
|
||||
{ "MB", 1048576},
|
||||
{ "GB", 1073741824}
|
||||
};
|
||||
static const std::string TRANSPARENT_MODE = "Transparent";
|
||||
|
||||
bool
|
||||
isModeInherited(const string &mode)
|
||||
{
|
||||
return mode == "as-top-level" || mode == "inherited";
|
||||
}
|
||||
|
||||
const std::string &
|
||||
getModeWithDefault(
|
||||
const std::string &mode,
|
||||
const std::string &default_mode,
|
||||
const std::unordered_map<std::string, std::string> &key_to_val)
|
||||
{
|
||||
if (isModeInherited(mode) && (key_to_val.find(default_mode) != key_to_val.end())) {
|
||||
dbgError(D_LOCAL_POLICY) << "Setting to top-level mode: " << default_mode;
|
||||
return key_to_val.at(default_mode);
|
||||
}
|
||||
else if (key_to_val.find(mode) == key_to_val.end()) {
|
||||
dbgError(D_LOCAL_POLICY) << "Given mode: " << mode << " or top-level: " << default_mode << " is invalid.";
|
||||
return key_to_val.at("inactive");
|
||||
}
|
||||
return key_to_val.at(mode);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecWebBotsURI::load(cereal::JSONInputArchive &archive_in)
|
||||
@@ -84,7 +116,7 @@ NewAppSecPracticeAntiBot::load(cereal::JSONInputArchive &archive_in)
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Web Bots";
|
||||
parseAppsecJSONKey<vector<NewAppSecWebBotsURI>>("injectedUris", injected_uris, archive_in);
|
||||
parseAppsecJSONKey<vector<NewAppSecWebBotsURI>>("validatedUris", validated_uris, archive_in);
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "Inactive");
|
||||
parseMandatoryAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Web Bots override mode invalid: " << override_mode;
|
||||
}
|
||||
@@ -110,26 +142,33 @@ NewAppSecWebAttackProtections::load(cereal::JSONInputArchive &archive_in)
|
||||
parseAppsecJSONKey<string>("csrfProtection", csrf_protection, archive_in, "inactive");
|
||||
parseAppsecJSONKey<string>("errorDisclosure", error_disclosure, archive_in, "inactive");
|
||||
parseAppsecJSONKey<string>("openRedirect", open_redirect, archive_in, "inactive");
|
||||
if (valid_modes.count(csrf_protection) == 0 ||
|
||||
valid_modes.count(error_disclosure) == 0 ||
|
||||
valid_modes.count(open_redirect) == 0) {
|
||||
string error_msg = "AppSec Attack Protections mode invalid. csrf_protection: " + csrf_protection +
|
||||
" error_disclosure: " + error_disclosure + " open_redirect: " + open_redirect;
|
||||
dbgWarning(D_LOCAL_POLICY) << error_msg;
|
||||
throw PolicyGenException(error_msg);
|
||||
}
|
||||
parseAppsecJSONKey<bool>("nonValidHttpMethods", non_valid_http_methods, archive_in, false);
|
||||
}
|
||||
|
||||
const string
|
||||
NewAppSecWebAttackProtections::getCsrfProtectionMode() const
|
||||
const string &
|
||||
NewAppSecWebAttackProtections::getCsrfProtectionMode(const string &default_mode) const
|
||||
{
|
||||
if (key_to_practices_val.find(csrf_protection) == key_to_practices_val.end()) {
|
||||
dbgError(D_LOCAL_POLICY)
|
||||
<< "Failed to find a value for "
|
||||
<< csrf_protection
|
||||
<< ". Setting CSRF protection to Inactive";
|
||||
return "Inactive";
|
||||
}
|
||||
return key_to_practices_val.at(csrf_protection);
|
||||
return getModeWithDefault(csrf_protection, default_mode, key_to_practices_val2);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecWebAttackProtections::getErrorDisclosureMode() const
|
||||
NewAppSecWebAttackProtections::getErrorDisclosureMode(const string &default_mode) const
|
||||
{
|
||||
return error_disclosure;
|
||||
return getModeWithDefault(error_disclosure, default_mode, key_to_practices_val2);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecWebAttackProtections::getOpenRedirectMode(const string &default_mode) const
|
||||
{
|
||||
return getModeWithDefault(open_redirect, default_mode, key_to_practices_val2);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -138,40 +177,24 @@ NewAppSecWebAttackProtections::getNonValidHttpMethods() const
|
||||
return non_valid_http_methods;
|
||||
}
|
||||
|
||||
const string
|
||||
NewAppSecWebAttackProtections::getOpenRedirectMode() const
|
||||
{
|
||||
if (key_to_practices_val.find(open_redirect) == key_to_practices_val.end()) {
|
||||
dbgError(D_LOCAL_POLICY)
|
||||
<< "Failed to find a value for "
|
||||
<< open_redirect
|
||||
<< ". Setting Open Redirect mode to Inactive";
|
||||
return "Inactive";
|
||||
}
|
||||
return key_to_practices_val.at(open_redirect);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecPracticeWebAttacks::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice web attacks spec";
|
||||
parseAppsecJSONKey<NewAppSecWebAttackProtections>("protections", protections, archive_in);
|
||||
parseAppsecJSONKey<string>("overrideMode", mode, archive_in, "Unset");
|
||||
parseMandatoryAppsecJSONKey<string>("overrideMode", mode, archive_in, "inactive");
|
||||
if (valid_modes.count(mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec practice override mode invalid: " << mode;
|
||||
}
|
||||
|
||||
if (getMode() == "Prevent") {
|
||||
parseMandatoryAppsecJSONKey<string>("minimumConfidence", minimum_confidence, archive_in, "critical");
|
||||
if (valid_confidences.count(minimum_confidence) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec practice override minimum confidence invalid: "
|
||||
<< minimum_confidence;
|
||||
throw PolicyGenException("AppSec practice override minimum confidence invalid: " + minimum_confidence);
|
||||
}
|
||||
} else {
|
||||
minimum_confidence = "Transparent";
|
||||
parseAppsecJSONKey<string>("minimumConfidence", minimum_confidence, archive_in, "critical");
|
||||
if (valid_confidences.count(minimum_confidence) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec practice override minimum confidence invalid: "
|
||||
<< minimum_confidence;
|
||||
throw PolicyGenException("AppSec practice override minimum confidence invalid: " + minimum_confidence);
|
||||
}
|
||||
|
||||
parseAppsecJSONKey<int>("maxBodySizeKb", max_body_size_kb, archive_in, 1000000);
|
||||
parseAppsecJSONKey<int>("maxHeaderSizeBytes", max_header_size_bytes, archive_in, 102400);
|
||||
parseAppsecJSONKey<int>("maxObjectDepth", max_object_depth, archive_in, 40);
|
||||
@@ -203,19 +226,25 @@ NewAppSecPracticeWebAttacks::getMaxUrlSizeBytes() const
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecPracticeWebAttacks::getMinimumConfidence() const
|
||||
NewAppSecPracticeWebAttacks::getMinimumConfidence(const string &default_mode) const
|
||||
{
|
||||
if (getMode(default_mode) != "Prevent") {
|
||||
return TRANSPARENT_MODE;
|
||||
}
|
||||
return minimum_confidence;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecPracticeWebAttacks::getMode(const string &default_mode) const
|
||||
{
|
||||
if (mode == "Unset" || (key_to_practices_val2.find(mode) == key_to_practices_val2.end())) {
|
||||
dbgError(D_LOCAL_POLICY) << "Couldn't find a value for key: " << mode << ". Returning " << default_mode;
|
||||
return default_mode;
|
||||
}
|
||||
return key_to_practices_val2.at(mode);
|
||||
const string &res = getModeWithDefault(mode, default_mode, key_to_practices_val);
|
||||
return res;
|
||||
}
|
||||
|
||||
const NewAppSecWebAttackProtections &
|
||||
NewAppSecPracticeWebAttacks::getProtections() const
|
||||
{
|
||||
return protections;
|
||||
}
|
||||
|
||||
SnortProtectionsSection::SnortProtectionsSection(
|
||||
@@ -244,7 +273,7 @@ SnortProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("context", context),
|
||||
cereal::make_nvp("mode", key_to_mode_val.at(mode)),
|
||||
cereal::make_nvp("mode", mode),
|
||||
cereal::make_nvp("files", files),
|
||||
cereal::make_nvp("assetName", asset_name),
|
||||
cereal::make_nvp("assetId", asset_id),
|
||||
@@ -440,8 +469,8 @@ void
|
||||
NewSnortSignaturesAndOpenSchemaAPI::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Snort Signatures practice";
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
parseMandatoryAppsecJSONKey<vector<string>>("configmap", config_map, archive_in);
|
||||
parseMandatoryAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
parseAppsecJSONKey<vector<string>>("configmap", config_map, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("files", files, archive_in);
|
||||
is_temporary = false;
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
@@ -457,9 +486,10 @@ NewSnortSignaturesAndOpenSchemaAPI::addFile(const string &file_name)
|
||||
}
|
||||
|
||||
const string &
|
||||
NewSnortSignaturesAndOpenSchemaAPI::getOverrideMode() const
|
||||
NewSnortSignaturesAndOpenSchemaAPI::getOverrideMode(const string &default_mode) const
|
||||
{
|
||||
return override_mode;
|
||||
const string &res = getModeWithDefault(override_mode, default_mode, key_to_practices_val);
|
||||
return res;
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
@@ -491,7 +521,7 @@ IpsProtectionsRulesSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
vector<string> protections;
|
||||
out_ar(
|
||||
cereal::make_nvp("action", key_to_mode_val.at(action)),
|
||||
cereal::make_nvp("action", action),
|
||||
cereal::make_nvp("confidenceLevel", confidence_level),
|
||||
cereal::make_nvp("clientProtections", true),
|
||||
cereal::make_nvp("serverProtections", true),
|
||||
@@ -541,7 +571,7 @@ IpsProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
cereal::make_nvp("practiceName", practice_name),
|
||||
cereal::make_nvp("practiceId", practice_id),
|
||||
cereal::make_nvp("sourceIdentifier", source_identifier),
|
||||
cereal::make_nvp("defaultAction", key_to_mode_val.at(mode)),
|
||||
cereal::make_nvp("defaultAction", mode),
|
||||
cereal::make_nvp("rules", rules)
|
||||
);
|
||||
}
|
||||
@@ -566,7 +596,7 @@ void
|
||||
NewIntrusionPrevention::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Intrusion Prevention practice";
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
parseMandatoryAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Intrusion Prevention override mode invalid: " << override_mode;
|
||||
throw PolicyGenException("AppSec Intrusion Prevention override mode invalid: " + override_mode);
|
||||
@@ -580,13 +610,13 @@ NewIntrusionPrevention::load(cereal::JSONInputArchive &archive_in)
|
||||
"AppSec Intrusion Prevention max performance impact invalid: " + max_performance_impact
|
||||
);
|
||||
}
|
||||
parseAppsecJSONKey<string>("minSeverityLevel", min_severity_level, archive_in, "low");
|
||||
parseAppsecJSONKey<string>("minSeverityLevel", min_severity_level, archive_in, "medium");
|
||||
if (severity_levels.count(min_severity_level) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention min severity level invalid: "
|
||||
<< min_severity_level;
|
||||
}
|
||||
parseAppsecJSONKey<string>("highConfidenceEventAction", high_confidence_event_action, archive_in, "prevent");
|
||||
parseAppsecJSONKey<string>("highConfidenceEventAction", high_confidence_event_action, archive_in, "inherited");
|
||||
if (confidences_actions.count(high_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention high confidence event invalid: "
|
||||
@@ -595,7 +625,9 @@ NewIntrusionPrevention::load(cereal::JSONInputArchive &archive_in)
|
||||
"AppSec Intrusion Prevention high confidence event invalid: " + high_confidence_event_action
|
||||
);
|
||||
}
|
||||
parseAppsecJSONKey<string>("mediumConfidenceEventAction", medium_confidence_event_action, archive_in, "prevent");
|
||||
parseAppsecJSONKey<string>(
|
||||
"mediumConfidenceEventAction", medium_confidence_event_action, archive_in, "inherited"
|
||||
);
|
||||
if (confidences_actions.count(medium_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention medium confidence event invalid: "
|
||||
@@ -613,16 +645,16 @@ NewIntrusionPrevention::load(cereal::JSONInputArchive &archive_in)
|
||||
"AppSec Intrusion Prevention low confidence event action invalid: " + low_confidence_event_action
|
||||
);
|
||||
}
|
||||
parseAppsecJSONKey<int>("minCveYear", min_cve_Year, archive_in);
|
||||
parseAppsecJSONKey<int>("minCveYear", min_cve_Year, archive_in, 2016);
|
||||
}
|
||||
|
||||
vector<IpsProtectionsRulesSection>
|
||||
NewIntrusionPrevention::createIpsRules() const
|
||||
NewIntrusionPrevention::createIpsRules(const string &default_mode) const
|
||||
{
|
||||
vector<IpsProtectionsRulesSection> ips_rules;
|
||||
IpsProtectionsRulesSection high_rule(
|
||||
min_cve_Year,
|
||||
high_confidence_event_action,
|
||||
getModeWithDefault(high_confidence_event_action, default_mode, key_to_practices_val),
|
||||
string("High"),
|
||||
max_performance_impact,
|
||||
string(""),
|
||||
@@ -632,7 +664,7 @@ NewIntrusionPrevention::createIpsRules() const
|
||||
|
||||
IpsProtectionsRulesSection med_rule(
|
||||
min_cve_Year,
|
||||
medium_confidence_event_action,
|
||||
getModeWithDefault(medium_confidence_event_action, default_mode, key_to_practices_val),
|
||||
string("Medium"),
|
||||
max_performance_impact,
|
||||
string(""),
|
||||
@@ -642,7 +674,7 @@ NewIntrusionPrevention::createIpsRules() const
|
||||
|
||||
IpsProtectionsRulesSection low_rule(
|
||||
min_cve_Year,
|
||||
low_confidence_event_action,
|
||||
getModeWithDefault(low_confidence_event_action, default_mode, key_to_practices_val),
|
||||
string("Low"),
|
||||
max_performance_impact,
|
||||
string(""),
|
||||
@@ -654,9 +686,10 @@ NewIntrusionPrevention::createIpsRules() const
|
||||
}
|
||||
|
||||
const std::string &
|
||||
NewIntrusionPrevention::getMode() const
|
||||
NewIntrusionPrevention::getMode(const std::string &default_mode) const
|
||||
{
|
||||
return override_mode;
|
||||
const string &res = getModeWithDefault(override_mode, default_mode, key_to_practices_val);
|
||||
return res;
|
||||
}
|
||||
|
||||
FileSecurityProtectionsSection::FileSecurityProtectionsSection(
|
||||
@@ -711,20 +744,20 @@ FileSecurityProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
cereal::make_nvp("assetId", asset_id),
|
||||
cereal::make_nvp("practiceName", practice_name),
|
||||
cereal::make_nvp("practiceId", practice_id),
|
||||
cereal::make_nvp("action", key_to_mode_val.at(action)),
|
||||
cereal::make_nvp("filesWithoutNameAction", key_to_mode_val.at(files_without_name_action)),
|
||||
cereal::make_nvp("action", action),
|
||||
cereal::make_nvp("filesWithoutNameAction", files_without_name_action),
|
||||
cereal::make_nvp("allowFilesWithoutName", allow_files_without_name),
|
||||
cereal::make_nvp("highConfidence", key_to_mode_val.at(high_confidence_action)),
|
||||
cereal::make_nvp("mediumConfidence", key_to_mode_val.at(medium_confidence_action)),
|
||||
cereal::make_nvp("lowConfidence", key_to_mode_val.at(low_confidence_action)),
|
||||
cereal::make_nvp("highConfidence", high_confidence_action),
|
||||
cereal::make_nvp("mediumConfidence", medium_confidence_action),
|
||||
cereal::make_nvp("lowConfidence", low_confidence_action),
|
||||
cereal::make_nvp("severityLevel", key_to_severity_level_val.at(severity_level)),
|
||||
cereal::make_nvp("fileSizeLimitAction", key_to_mode_val.at(file_size_limit_action)),
|
||||
cereal::make_nvp("fileSizeLimitAction", file_size_limit_action),
|
||||
cereal::make_nvp("fileSizeLimit", file_size_limit),
|
||||
cereal::make_nvp("requiredFileSizeLimit", required_file_size_limit),
|
||||
cereal::make_nvp("requiredArchiveExtraction", required_archive_extraction),
|
||||
cereal::make_nvp("archiveFileSizeLimit", archive_file_size_limit),
|
||||
cereal::make_nvp("MultiLevelArchiveAction", key_to_mode_val.at(multi_level_archive_action)),
|
||||
cereal::make_nvp("UnopenedArchiveAction", key_to_mode_val.at(unopened_archive_action))
|
||||
cereal::make_nvp("MultiLevelArchiveAction", multi_level_archive_action),
|
||||
cereal::make_nvp("UnopenedArchiveAction", unopened_archive_action)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -748,7 +781,7 @@ void
|
||||
NewFileSecurityArchiveInspection::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec File Security Archive Inspection practice";
|
||||
parseAppsecJSONKey<bool>("extractArchiveFiles", extract_archive_files, archive_in, true);
|
||||
parseAppsecJSONKey<bool>("extractArchiveFiles", extract_archive_files, archive_in, false);
|
||||
parseAppsecJSONKey<uint64_t>("scanMaxFileSize", scan_max_file_size, archive_in, 10);
|
||||
parseAppsecJSONKey<string>("scanMaxFileSizeUnit", scan_max_file_size_unit, archive_in, "MB");
|
||||
if (size_unit.count(scan_max_file_size_unit) == 0) {
|
||||
@@ -763,7 +796,7 @@ NewFileSecurityArchiveInspection::load(cereal::JSONInputArchive &archive_in)
|
||||
"archivedFilesWithinArchivedFiles",
|
||||
archived_files_within_archived_files,
|
||||
archive_in,
|
||||
"prevent");
|
||||
"inherited");
|
||||
if (confidences_actions.count(archived_files_within_archived_files) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security Archive Inspection archived files within archived files invalid: "
|
||||
@@ -777,7 +810,7 @@ NewFileSecurityArchiveInspection::load(cereal::JSONInputArchive &archive_in)
|
||||
"archivedFilesWhereContentExtractionFailed",
|
||||
archived_files_where_content_extraction_failed,
|
||||
archive_in,
|
||||
"prevent");
|
||||
"inherited");
|
||||
if (confidences_actions.count(archived_files_where_content_extraction_failed) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security Archive Inspection archived files within archived file invalid: "
|
||||
@@ -834,7 +867,7 @@ NewFileSecurityLargeFileInspection::load(cereal::JSONInputArchive &archive_in)
|
||||
"filesExceedingSizeLimitAction",
|
||||
files_exceeding_size_limit_action,
|
||||
archive_in,
|
||||
"prevent");
|
||||
"inherited");
|
||||
if (confidences_actions.count(files_exceeding_size_limit_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security Archive Inspection archived files within archived files invalid: "
|
||||
@@ -869,18 +902,18 @@ void
|
||||
NewFileSecurity::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec File Security practice";
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
parseMandatoryAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec File Security override mode invalid: " << override_mode;
|
||||
throw PolicyGenException("AppSec File Security override mode invalid: " + override_mode);
|
||||
}
|
||||
parseMandatoryAppsecJSONKey<string>("minSeverityLevel", min_severity_level, archive_in, "low");
|
||||
parseAppsecJSONKey<string>("minSeverityLevel", min_severity_level, archive_in, "medium");
|
||||
if (severity_levels.count(min_severity_level) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec File Security min severity level invalid: " << min_severity_level;
|
||||
min_severity_level = "low";
|
||||
}
|
||||
parseMandatoryAppsecJSONKey<string>(
|
||||
"highConfidenceEventAction", high_confidence_event_action, archive_in, "inactive"
|
||||
parseAppsecJSONKey<string>(
|
||||
"highConfidenceEventAction", high_confidence_event_action, archive_in, "inherited"
|
||||
);
|
||||
if (confidences_actions.count(high_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
@@ -888,8 +921,8 @@ NewFileSecurity::load(cereal::JSONInputArchive &archive_in)
|
||||
<< high_confidence_event_action;
|
||||
high_confidence_event_action = "inactive";
|
||||
}
|
||||
parseMandatoryAppsecJSONKey<string>(
|
||||
"mediumConfidenceEventAction", medium_confidence_event_action, archive_in, "inactive"
|
||||
parseAppsecJSONKey<string>(
|
||||
"mediumConfidenceEventAction", medium_confidence_event_action, archive_in, "inherited"
|
||||
);
|
||||
if (confidences_actions.count(medium_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
@@ -897,8 +930,8 @@ NewFileSecurity::load(cereal::JSONInputArchive &archive_in)
|
||||
<< medium_confidence_event_action;
|
||||
medium_confidence_event_action = "inactive";
|
||||
}
|
||||
parseMandatoryAppsecJSONKey<string>(
|
||||
"lowConfidenceEventAction", low_confidence_event_action, archive_in, "inactive"
|
||||
parseAppsecJSONKey<string>(
|
||||
"lowConfidenceEventAction", low_confidence_event_action, archive_in, "detect"
|
||||
);
|
||||
if (confidences_actions.count(low_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
@@ -906,7 +939,7 @@ NewFileSecurity::load(cereal::JSONInputArchive &archive_in)
|
||||
<< low_confidence_event_action;
|
||||
low_confidence_event_action = "inactive";
|
||||
}
|
||||
parseMandatoryAppsecJSONKey<string>("unnamedFilesAction", unnamed_files_action, archive_in, "inactive");
|
||||
parseAppsecJSONKey<string>("unnamedFilesAction", unnamed_files_action, archive_in, "inherited");
|
||||
if (confidences_actions.count(unnamed_files_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security low unnamed files action invalid: "
|
||||
@@ -914,10 +947,8 @@ NewFileSecurity::load(cereal::JSONInputArchive &archive_in)
|
||||
unnamed_files_action = "inactive";
|
||||
}
|
||||
parseAppsecJSONKey<bool>("threatEmulationEnabled", threat_emulation_enabled, archive_in);
|
||||
parseMandatoryAppsecJSONKey<NewFileSecurityArchiveInspection>("archiveInspection", archive_inspection, archive_in);
|
||||
parseMandatoryAppsecJSONKey<NewFileSecurityLargeFileInspection>(
|
||||
"largeFileInspection", large_file_inspection, archive_in
|
||||
);
|
||||
parseAppsecJSONKey<NewFileSecurityArchiveInspection>("archiveInspection", archive_inspection, archive_in);
|
||||
parseAppsecJSONKey<NewFileSecurityLargeFileInspection>("largeFileInspection", large_file_inspection, archive_in);
|
||||
}
|
||||
|
||||
const string &
|
||||
@@ -944,28 +975,37 @@ NewFileSecurity::createFileSecurityProtectionsSection(
|
||||
const string &asset_name,
|
||||
const string &asset_id,
|
||||
const string &practice_name,
|
||||
const string &practice_id) const
|
||||
const string &practice_id,
|
||||
const string &default_mode) const
|
||||
{
|
||||
string practice_action = (isModeInherited(override_mode) ? default_mode : override_mode);
|
||||
const string &unnamed_files_action_val =
|
||||
getModeWithDefault(unnamed_files_action, practice_action, key_to_mode_val);
|
||||
const string &large_file_action_val = getModeWithDefault(
|
||||
getLargeFileInspection().getFileSizeLimitAction(),
|
||||
practice_action,
|
||||
key_to_mode_val
|
||||
);
|
||||
return FileSecurityProtectionsSection(
|
||||
getLargeFileInspection().getFileSizeLimit(),
|
||||
getArchiveInspection().getArchiveFileSizeLimit(),
|
||||
unnamed_files_action == "prevent" ? true : false,
|
||||
getLargeFileInspection().getFileSizeLimitAction() == "prevent" ? true : false,
|
||||
unnamed_files_action_val == "Prevent" ? true : false,
|
||||
large_file_action_val == "Prevent" ? true : false,
|
||||
getArchiveInspection().getrequiredArchiveExtraction(),
|
||||
context,
|
||||
asset_name,
|
||||
asset_id,
|
||||
practice_name,
|
||||
practice_id,
|
||||
override_mode,
|
||||
unnamed_files_action,
|
||||
high_confidence_event_action,
|
||||
medium_confidence_event_action,
|
||||
low_confidence_event_action,
|
||||
getModeWithDefault(override_mode, practice_action, key_to_mode_val),
|
||||
unnamed_files_action_val,
|
||||
getModeWithDefault(high_confidence_event_action, practice_action, key_to_mode_val),
|
||||
getModeWithDefault(medium_confidence_event_action, practice_action, key_to_mode_val),
|
||||
getModeWithDefault(low_confidence_event_action, practice_action, key_to_mode_val),
|
||||
min_severity_level,
|
||||
getLargeFileInspection().getFileSizeLimitAction(),
|
||||
getArchiveInspection().getMultiLevelArchiveAction(),
|
||||
getArchiveInspection().getUnopenedArchiveAction()
|
||||
large_file_action_val,
|
||||
getModeWithDefault(getArchiveInspection().getMultiLevelArchiveAction(), practice_action, key_to_mode_val),
|
||||
getModeWithDefault(getArchiveInspection().getUnopenedArchiveAction(), practice_action, key_to_mode_val)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -974,14 +1014,14 @@ NewAppSecPracticeSpec::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice spec";
|
||||
parseAppsecJSONKey<NewSnortSignaturesAndOpenSchemaAPI>(
|
||||
"openapi-schema-validation",
|
||||
"schemaValidation",
|
||||
openapi_schema_validation,
|
||||
archive_in
|
||||
);
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<NewFileSecurity>("fileSecurity", file_security, archive_in);
|
||||
parseAppsecJSONKey<NewIntrusionPrevention>("intrusionPrevention", intrusion_prevention, archive_in);
|
||||
parseAppsecJSONKey<NewSnortSignaturesAndOpenSchemaAPI>("snortSignatures", snort_signatures, archive_in);
|
||||
parseMandatoryAppsecJSONKey<NewFileSecurity>("fileSecurity", file_security, archive_in);
|
||||
parseMandatoryAppsecJSONKey<NewIntrusionPrevention>("intrusionPrevention", intrusion_prevention, archive_in);
|
||||
parseMandatoryAppsecJSONKey<NewSnortSignaturesAndOpenSchemaAPI>("snortSignatures", snort_signatures, archive_in);
|
||||
parseMandatoryAppsecJSONKey<NewAppSecPracticeWebAttacks>("webAttacks", web_attacks, archive_in);
|
||||
parseAppsecJSONKey<NewAppSecPracticeAntiBot>("antiBot", anti_bot, archive_in);
|
||||
parseAppsecJSONKey<string>("name", practice_name, archive_in);
|
||||
|
||||
@@ -996,13 +996,15 @@ PolicyMakerUtils::createIpsSections(
|
||||
const string &source_identifier,
|
||||
const string & context,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
map<AnnotationTypes, string> &rule_annotations)
|
||||
map<AnnotationTypes, string> &rule_annotations,
|
||||
const string &default_mode)
|
||||
{
|
||||
auto apssec_practice = getAppsecPracticeSpec<V1beta2AppsecLinuxPolicy, NewAppSecPracticeSpec>(
|
||||
rule_annotations[AnnotationTypes::PRACTICE],
|
||||
policy);
|
||||
|
||||
if (apssec_practice.getIntrusionPrevention().getMode().empty()) return;
|
||||
const string &override_mode = apssec_practice.getIntrusionPrevention().getMode(default_mode);
|
||||
if (override_mode == "Inactive" || override_mode == "Disabled") return;
|
||||
|
||||
IpsProtectionsSection ips_section = IpsProtectionsSection(
|
||||
context,
|
||||
@@ -1011,8 +1013,8 @@ PolicyMakerUtils::createIpsSections(
|
||||
practice_name,
|
||||
practice_id,
|
||||
source_identifier,
|
||||
apssec_practice.getIntrusionPrevention().getMode(),
|
||||
apssec_practice.getIntrusionPrevention().createIpsRules()
|
||||
override_mode,
|
||||
apssec_practice.getIntrusionPrevention().createIpsRules(override_mode)
|
||||
);
|
||||
|
||||
ips[asset_name] = ips_section;
|
||||
@@ -1068,13 +1070,16 @@ PolicyMakerUtils::createSnortSections(
|
||||
const string &practice_id,
|
||||
const string &source_identifier,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
map<AnnotationTypes, string> &rule_annotations)
|
||||
map<AnnotationTypes, string> &rule_annotations,
|
||||
const string &default_mode)
|
||||
{
|
||||
auto apssec_practice = getAppsecPracticeSpec<V1beta2AppsecLinuxPolicy, NewAppSecPracticeSpec>(
|
||||
rule_annotations[AnnotationTypes::PRACTICE],
|
||||
policy);
|
||||
|
||||
if (apssec_practice.getSnortSignatures().getOverrideMode() == "inactive" ||
|
||||
const string &override_mode = apssec_practice.getSnortSignatures().getOverrideMode(default_mode);
|
||||
if (override_mode == "Inactive" ||
|
||||
override_mode == "Disabled" ||
|
||||
apssec_practice.getSnortSignatures().getFiles().size() == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -1094,7 +1099,7 @@ PolicyMakerUtils::createSnortSections(
|
||||
practice_name,
|
||||
practice_id,
|
||||
source_identifier,
|
||||
apssec_practice.getSnortSignatures().getOverrideMode(),
|
||||
override_mode,
|
||||
apssec_practice.getSnortSignatures().getFiles()
|
||||
);
|
||||
|
||||
@@ -1109,7 +1114,8 @@ PolicyMakerUtils::createFileSecuritySections(
|
||||
const string &practice_name,
|
||||
const string &context,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
map<AnnotationTypes, string> &rule_annotations)
|
||||
map<AnnotationTypes, string> &rule_annotations,
|
||||
const string &default_mode)
|
||||
{
|
||||
auto apssec_practice = getAppsecPracticeSpec<V1beta2AppsecLinuxPolicy, NewAppSecPracticeSpec>(
|
||||
rule_annotations[AnnotationTypes::PRACTICE],
|
||||
@@ -1122,7 +1128,8 @@ PolicyMakerUtils::createFileSecuritySections(
|
||||
asset_name,
|
||||
asset_id,
|
||||
practice_name,
|
||||
practice_id
|
||||
practice_id,
|
||||
default_mode
|
||||
);
|
||||
|
||||
file_security[asset_name] = file_security_section;
|
||||
@@ -1134,6 +1141,7 @@ PolicyMakerUtils::createRateLimitSection(
|
||||
const string &url,
|
||||
const string &uri,
|
||||
const string &trigger_id,
|
||||
const std::string &default_mode,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
map<AnnotationTypes, string> &rule_annotations)
|
||||
{
|
||||
@@ -1157,13 +1165,13 @@ PolicyMakerUtils::createRateLimitSection(
|
||||
trigger = RateLimitRulesTriggerSection(trigger_id, trigger_name, "Trigger");
|
||||
}
|
||||
|
||||
auto rules = access_control_practice.geRateLimit().createRateLimitRulesSection(trigger);
|
||||
auto rules = access_control_practice.getRateLimit().createRateLimitRulesSection(trigger);
|
||||
|
||||
rate_limit[rule_annotations[AnnotationTypes::ACCESS_CONTROL_PRACTICE]] = RateLimitSection(
|
||||
asset_name,
|
||||
url,
|
||||
uri,
|
||||
access_control_practice.geRateLimit().getMode(),
|
||||
access_control_practice.getRateLimit().getMode(default_mode),
|
||||
practice_id,
|
||||
rule_annotations[AnnotationTypes::ACCESS_CONTROL_PRACTICE],
|
||||
rules
|
||||
@@ -1198,12 +1206,13 @@ PolicyMakerUtils::createWebAppSection(
|
||||
practice_id,
|
||||
rule_annotations[AnnotationTypes::PRACTICE],
|
||||
rule_config.getContext(),
|
||||
apssec_practice.getWebAttacks().getMinimumConfidence(),
|
||||
apssec_practice.getWebAttacks().getMinimumConfidence(default_mode),
|
||||
apssec_practice.getWebAttacks().getMode(default_mode),
|
||||
practice_advance_config,
|
||||
apssec_practice.getAntiBot(),
|
||||
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]],
|
||||
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]]
|
||||
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]],
|
||||
apssec_practice.getWebAttacks().getProtections()
|
||||
);
|
||||
web_apps[rule_config.getAssetName()] = web_app;
|
||||
}
|
||||
@@ -1271,7 +1280,8 @@ PolicyMakerUtils::createThreatPreventionPracticeSections(
|
||||
current_identifier,
|
||||
rule_config.getContext(),
|
||||
policy,
|
||||
rule_annotations
|
||||
rule_annotations,
|
||||
default_mode
|
||||
);
|
||||
|
||||
createSnortSections(
|
||||
@@ -1282,7 +1292,8 @@ PolicyMakerUtils::createThreatPreventionPracticeSections(
|
||||
practice_id,
|
||||
current_identifier,
|
||||
policy,
|
||||
rule_annotations
|
||||
rule_annotations,
|
||||
default_mode
|
||||
);
|
||||
|
||||
createFileSecuritySections(
|
||||
@@ -1292,11 +1303,18 @@ PolicyMakerUtils::createThreatPreventionPracticeSections(
|
||||
rule_annotations[AnnotationTypes::PRACTICE],
|
||||
"assetId(" + rule_config.getAssetId() + ")",
|
||||
policy,
|
||||
rule_annotations
|
||||
rule_annotations,
|
||||
default_mode
|
||||
);
|
||||
|
||||
if (!web_apps.count(rule_config.getAssetName())) {
|
||||
createWebAppSection(policy, rule_config, practice_id, asset_name, default_mode, rule_annotations);
|
||||
createWebAppSection(
|
||||
policy,
|
||||
rule_config,
|
||||
practice_id,
|
||||
asset_name,
|
||||
default_mode,
|
||||
rule_annotations);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1568,6 +1586,7 @@ PolicyMakerUtils::createPolicyElementsByRule<V1beta2AppsecLinuxPolicy, NewParsed
|
||||
std::get<0>(splited_host_name),
|
||||
std::get<2>(splited_host_name),
|
||||
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]].getTriggerId(),
|
||||
rule.getMode(),
|
||||
policy,
|
||||
rule_annotations
|
||||
);
|
||||
|
||||
@@ -216,6 +216,18 @@ getFecApplicable(const string &command_output)
|
||||
return genError("Could not determine if fec applicable");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getSMCBasedMgmtId(const string &command_output)
|
||||
{
|
||||
return getAttr(command_output, "Mgmt object UUID was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getSMCBasedMgmtName(const string &command_output)
|
||||
{
|
||||
return getAttr(command_output, "Mgmt object Name was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getSmbObjectName(const string &command_output)
|
||||
{
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
SHELL_PRE_CMD("read sdwan data",
|
||||
"(cpsdwan get_data > /tmp/cpsdwan_getdata_orch.json~) "
|
||||
"&& (mv /tmp/cpsdwan_getdata_orch.json~ /tmp/cpsdwan_getdata_orch.json)")
|
||||
#endif
|
||||
#endif //gaia || smb
|
||||
#if defined(smb)
|
||||
SHELL_PRE_CMD("gunzip local.cfg", "gunzip -c $FWDIR/state/local/FW1/local.cfg.gz > /tmp/local.cfg")
|
||||
#endif //smb
|
||||
#endif
|
||||
|
||||
#ifdef SHELL_CMD_HANDLER
|
||||
@@ -115,6 +118,22 @@ SHELL_CMD_HANDLER(
|
||||
"cat $FWDIR/database/myself_objects.C | awk -F '[:()]' '/:VPN_1/ {print $3}' | head -n 1",
|
||||
getGWIPSecVPNBlade
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"SMCBasedMgmtId",
|
||||
"domain_uuid=$(jq -r .domain_uuid /tmp/cpsdwan_getdata_orch.json);"
|
||||
"[ \"$domain_uuid\" != \"null\" ] && echo \"$domain_uuid\" ||"
|
||||
"cat $FWDIR/database/myself_objects.C "
|
||||
"| awk -F'[{}]' '/:masters/ { found=1; next } found && /:Uid/ { uid=tolower($2); print uid; exit }'",
|
||||
getSMCBasedMgmtId
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"SMCBasedMgmtName",
|
||||
"domain_name=$(jq -r .domain_name /tmp/cpsdwan_getdata_orch.json);"
|
||||
"[ \"$domain_name\" != \"null\" ] && echo \"$domain_name\" ||"
|
||||
"cat $FWDIR/database/myself_objects.C "
|
||||
"| awk -F '[:()]' '/:masters/ {found=1; next} found && /:Name/ {print $3; exit}'",
|
||||
getSMCBasedMgmtName
|
||||
)
|
||||
#endif //gaia
|
||||
|
||||
#if defined(smb)
|
||||
@@ -148,6 +167,23 @@ SHELL_CMD_HANDLER(
|
||||
"cat $FWDIR/conf/active_blades.txt | grep -o 'IPS [01]' | cut -d ' ' -f2",
|
||||
getSmbGWIPSecVPNBlade
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"SMCBasedMgmtId",
|
||||
"domain_uuid=$(jq -r .domain_uuid /tmp/cpsdwan_getdata_orch.json);"
|
||||
"[ \"$domain_uuid\" != \"null\" ] && echo \"$domain_uuid\" ||"
|
||||
"cat /tmp/local.cfg "
|
||||
"| awk -F'[{}]' '/:masters/ { found=1; next } found && /:Uid/ { uid=tolower($2); print uid; exit }'",
|
||||
getSMCBasedMgmtId
|
||||
)
|
||||
|
||||
SHELL_CMD_HANDLER(
|
||||
"SMCBasedMgmtName",
|
||||
"domain_name=$(jq -r .domain_name /tmp/cpsdwan_getdata_orch.json);"
|
||||
"[ \"$domain_name\" != \"null\" ] && echo \"$domain_name\" ||"
|
||||
"cat /tmp/local.cfg "
|
||||
"| awk -F '[:()]' '/:masters/ {found=1; next} found && /:Name/ {print $3; exit}'",
|
||||
getSMCBasedMgmtName
|
||||
)
|
||||
#endif//smb
|
||||
|
||||
SHELL_CMD_OUTPUT("kernel_version", "uname -r")
|
||||
@@ -190,3 +226,9 @@ FILE_CONTENT_HANDLER("os_release", "/etc/os-release", getOsRelease)
|
||||
FILE_CONTENT_HANDLER("AppSecModelVersion", "/etc/cp/conf/waap/waap.data", getWaapModelVersion)
|
||||
|
||||
#endif // FILE_CONTENT_HANDLER
|
||||
|
||||
#ifdef SHELL_POST_CMD
|
||||
#if defined(smb)
|
||||
SHELL_POST_CMD("remove local.cfg", "rm -rf /tmp/local.cfg")
|
||||
#endif //smb
|
||||
#endif
|
||||
|
||||
@@ -64,6 +64,12 @@ private:
|
||||
#undef FILE_CONTENT_HANDLER
|
||||
};
|
||||
|
||||
#define SHELL_POST_CMD(NAME, COMMAND) {NAME, COMMAND},
|
||||
map<string, string> shell_post_commands = {
|
||||
#include "details_resolver_impl.h"
|
||||
};
|
||||
#undef SHELL_POST_CMD
|
||||
|
||||
map<string, string>
|
||||
DetailsResolvingHanlder::Impl::getResolvedDetails() const
|
||||
{
|
||||
@@ -114,6 +120,18 @@ DetailsResolvingHanlder::Impl::getResolvedDetails() const
|
||||
in_file->close();
|
||||
}
|
||||
|
||||
for (auto &shell_post_command : shell_post_commands) {
|
||||
const string &name = shell_post_command.first;
|
||||
const string &command = shell_post_command.second;
|
||||
Maybe<int> command_ret = shell->getExecReturnCode(command, timeout);
|
||||
|
||||
if (!command_ret.ok()) {
|
||||
dbgWarning(D_AGENT_DETAILS) << "Failed to run post-command " << name;
|
||||
} else if (*command_ret) {
|
||||
dbgWarning(D_AGENT_DETAILS) << "Post-command " << name << " failed (rc: " << *command_ret << ")";
|
||||
}
|
||||
}
|
||||
|
||||
I_AgentDetailsReporter *reporter = Singleton::Consume<I_AgentDetailsReporter>::by<DetailsResolvingHanlder>();
|
||||
reporter->addAttr(resolved_details, true);
|
||||
|
||||
|
||||
@@ -1012,10 +1012,11 @@ private:
|
||||
HybridModeMetricEvent().notify();
|
||||
|
||||
if (!response.ok()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to get the update. Error: " << response.getErr();
|
||||
orch_status->setFieldStatus(
|
||||
OrchestrationStatusFieldType::LAST_UPDATE,
|
||||
OrchestrationStatusResult::FAILED,
|
||||
response.getErr()
|
||||
"Warning: Agent/Gateway failed during the update process. Contact Check Point support."
|
||||
);
|
||||
|
||||
return genError(response.getErr());
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
"/api/v1/agents/events",
|
||||
_,
|
||||
MessageCategory::LOG,
|
||||
_,
|
||||
_
|
||||
)).WillRepeatedly(SaveArg<2>(&message_body));
|
||||
|
||||
|
||||
@@ -473,10 +473,11 @@ FogAuthenticator::authenticateAgent()
|
||||
auto orc_status = Singleton::Consume<I_OrchestrationStatus>::by<FogAuthenticator>();
|
||||
credentials = getCredentials();
|
||||
if (!credentials.ok()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to authenticate the agent: " << credentials.getErr();
|
||||
orc_status->setFieldStatus(
|
||||
OrchestrationStatusFieldType::REGISTRATION,
|
||||
OrchestrationStatusResult::FAILED,
|
||||
credentials.getErr()
|
||||
"Warning: Agent/Gateway failed the authentication. Contact Check Point support."
|
||||
);
|
||||
return genError(credentials.getErr());
|
||||
}
|
||||
@@ -516,7 +517,7 @@ FogAuthenticator::authenticateAgent()
|
||||
orc_status->setFieldStatus(
|
||||
OrchestrationStatusFieldType::REGISTRATION,
|
||||
OrchestrationStatusResult::FAILED,
|
||||
access_token.getErr()
|
||||
"Warning: Agent/Gateway failed to receive access token. Contact Check Point support."
|
||||
);
|
||||
}
|
||||
int next_session_req = max(
|
||||
|
||||
@@ -154,6 +154,7 @@ protected:
|
||||
if (agentDetails->getOrchestrationMode() == OrchestrationMode::HYBRID) {
|
||||
MessageMetadata req_md(getSharedStorageHost(), 80);
|
||||
req_md.insertHeader("X-Tenant-Id", agentDetails->getTenantId());
|
||||
req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
||||
auto req_status = messaging->sendSyncMessage(
|
||||
method,
|
||||
uri,
|
||||
@@ -161,6 +162,10 @@ protected:
|
||||
MessageCategory::GENERIC,
|
||||
req_md
|
||||
);
|
||||
if (!req_status.ok()) {
|
||||
dbgWarning(D_WAAP) << "failed to send request to uri: " << uri
|
||||
<< ", error: " << req_status.getErr().toString();
|
||||
}
|
||||
return req_status.ok();
|
||||
}
|
||||
auto req_status = messaging->sendSyncMessage(
|
||||
@@ -169,6 +174,10 @@ protected:
|
||||
obj,
|
||||
MessageCategory::GENERIC
|
||||
);
|
||||
if (!req_status.ok()) {
|
||||
dbgWarning(D_WAAP) << "failed to send request to uri: " << uri
|
||||
<< ", error: " << req_status.getErr().toString();
|
||||
}
|
||||
return req_status.ok();
|
||||
}
|
||||
|
||||
@@ -204,6 +213,7 @@ protected:
|
||||
if (agentDetails->getOrchestrationMode() == OrchestrationMode::HYBRID) {
|
||||
MessageMetadata req_md(getSharedStorageHost(), 80);
|
||||
req_md.insertHeader("X-Tenant-Id", agentDetails->getTenantId());
|
||||
req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
||||
return messaging->sendSyncMessageWithoutResponse(
|
||||
method,
|
||||
uri,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "../waap_clib/WaapOpenRedirect.h"
|
||||
#include "../waap_clib/FpMitigation.h"
|
||||
#include "../waap_clib/DeepParser.h"
|
||||
#include "../waap_clib/OASchemaUpdaterConfConstant.h"
|
||||
#include "http_inspection_events.h"
|
||||
|
||||
enum HeaderType {
|
||||
@@ -29,6 +30,7 @@ enum HeaderType {
|
||||
COOKIE_HEADER,
|
||||
REFERER_HEADER,
|
||||
CONTENT_TYPE_HEADER,
|
||||
AUTHORIZATION_HEADER,
|
||||
CLEAN_HEADER,
|
||||
OTHER_KNOWN_HEADERS
|
||||
};
|
||||
@@ -135,6 +137,7 @@ public:
|
||||
virtual void add_response_body_chunk(const char* data, int data_len) = 0;
|
||||
virtual void end_response_body() = 0;
|
||||
virtual void end_response() = 0;
|
||||
virtual const std::string& getResponseBody() = 0;
|
||||
|
||||
virtual void collectFoundPatterns() = 0;
|
||||
virtual ReportIS::Severity computeEventSeverityFromDecision() const = 0;
|
||||
|
||||
@@ -86,6 +86,7 @@ add_library(waap_clib
|
||||
ParserPercentEncode.cc
|
||||
ParserPairs.cc
|
||||
Waf2Util2.cc
|
||||
ParserPDF.cc
|
||||
)
|
||||
|
||||
add_definitions("-Wno-unused-function")
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ParserPercentEncode.h"
|
||||
#include "ParserPairs.h"
|
||||
#include "ParserDelimiter.h"
|
||||
#include "ParserPDF.h"
|
||||
#include "WaapAssetState.h"
|
||||
#include "Waf2Regex.h"
|
||||
#include "Waf2Util.h"
|
||||
@@ -1146,9 +1147,15 @@ DeepParser::createInternalParser(
|
||||
));
|
||||
offset = 0;
|
||||
} else if (isTopData && (isBinaryType || m_pWaapAssetState->isBinarySampleType(cur_val))) {
|
||||
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse a binary file";
|
||||
m_parsersDeque.push_back(std::make_shared<BufferedParser<ParserBinary>>(*this, parser_depth + 1));
|
||||
offset = 0;
|
||||
if (isPDFDetected(cur_val)) {
|
||||
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse a PDF file";
|
||||
m_parsersDeque.push_back(std::make_shared<BufferedParser<ParserPDF>>(*this, parser_depth + 1));
|
||||
offset = 0;
|
||||
} else {
|
||||
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse a binary file";
|
||||
m_parsersDeque.push_back(std::make_shared<BufferedParser<ParserBinary>>(*this, parser_depth + 1));
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (offset < 0) {
|
||||
@@ -1473,3 +1480,12 @@ DeepParser::shouldEnforceDepthLimit(const std::shared_ptr<ParserBase> &parser) c
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DeepParser::isPDFDetected(const std::string &cur_val) const
|
||||
{
|
||||
static const std::string PDF_header("%PDF-");
|
||||
if (cur_val.size() < 10)
|
||||
return false;
|
||||
return cur_val.substr(0, cur_val.size() > 64 ? 64 : cur_val.size()).find(PDF_header) != std::string::npos;
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ private:
|
||||
bool shouldEnforceDepthLimit(const std::shared_ptr<ParserBase>& parser) const;
|
||||
void setLocalMaxObjectDepth(size_t depth) { m_localMaxObjectDepth = depth; }
|
||||
void setGlobalMaxObjectDepthReached() { m_globalMaxObjectDepthReached = true; }
|
||||
bool isPDFDetected(const std::string &cur_val) const;
|
||||
bool m_deepParserFlag;
|
||||
std::stack<std::tuple<size_t, size_t, std::string>> m_splitTypesStack; // depth, splitIndex, splitType
|
||||
std::deque<std::shared_ptr<ParserBase>> m_parsersDeque;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
111
components/security_apps/waap/waap_clib/ParserPDF.cc
Normal file
111
components/security_apps/waap/waap_clib/ParserPDF.cc
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ParserPDF.h"
|
||||
#include "Waf2Util.h"
|
||||
#include "debug.h"
|
||||
#include <string.h>
|
||||
|
||||
USE_DEBUG_FLAG(D_WAAP_PARSER_PDF);
|
||||
USE_DEBUG_FLAG(D_WAAP);
|
||||
|
||||
const std::string ParserPDF::m_parserName = "ParserPDF";
|
||||
const char* PDF_TAIL = "%%EOF";
|
||||
|
||||
ParserPDF::ParserPDF(
|
||||
IParserStreamReceiver &receiver,
|
||||
size_t parser_depth
|
||||
) :
|
||||
m_receiver(receiver),
|
||||
m_state(s_start),
|
||||
m_parser_depth(parser_depth)
|
||||
{}
|
||||
|
||||
ParserPDF::~ParserPDF()
|
||||
{}
|
||||
|
||||
size_t
|
||||
ParserPDF::push(const char *buf, size_t len)
|
||||
{
|
||||
dbgTrace(D_WAAP_PARSER_PDF)
|
||||
<< "buf="
|
||||
<< buf
|
||||
<< "len="
|
||||
<< len;
|
||||
|
||||
const char *c;
|
||||
|
||||
if (m_state == s_error) {
|
||||
return 0;
|
||||
}
|
||||
if (len == 0)
|
||||
{
|
||||
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): end of stream. m_state=" << m_state;
|
||||
|
||||
if (m_state == s_end) {
|
||||
m_receiver.onKvDone();
|
||||
} else {
|
||||
m_state = s_error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (m_state) {
|
||||
case s_start:
|
||||
m_state = s_body;
|
||||
CP_FALL_THROUGH;
|
||||
case s_body:
|
||||
c = strstr(buf + len - MAX_TAIL_LOOKUP, PDF_TAIL);
|
||||
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): c=" << c;
|
||||
if (c) {
|
||||
m_state = s_end;
|
||||
CP_FALL_THROUGH;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case s_end:
|
||||
if (m_receiver.onKey("PDF", 3) != 0) {
|
||||
m_state = s_error;
|
||||
return 0;
|
||||
}
|
||||
if (m_receiver.onValue("", 0) != 0) {
|
||||
m_state = s_error;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case s_error:
|
||||
break;
|
||||
default:
|
||||
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): unknown state: " << m_state;
|
||||
m_state = s_error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void ParserPDF::finish()
|
||||
{
|
||||
push(NULL, 0);
|
||||
}
|
||||
|
||||
const std::string& ParserPDF::name() const
|
||||
{
|
||||
return m_parserName;
|
||||
}
|
||||
|
||||
bool ParserPDF::error() const
|
||||
{
|
||||
return m_state == s_error;
|
||||
}
|
||||
47
components/security_apps/waap/waap_clib/ParserPDF.h
Normal file
47
components/security_apps/waap/waap_clib/ParserPDF.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __PARSER_PDF_H__
|
||||
#define __PARSER_PDF_H__
|
||||
|
||||
#include "ParserBase.h"
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_HEADER_LOOKUP 64
|
||||
#define MAX_TAIL_LOOKUP 5
|
||||
|
||||
class ParserPDF : public ParserBase {
|
||||
public:
|
||||
ParserPDF(IParserStreamReceiver &receiver, size_t parser_depth);
|
||||
virtual ~ParserPDF();
|
||||
virtual size_t push(const char *buf, size_t len);
|
||||
virtual void finish();
|
||||
virtual const std::string &name() const;
|
||||
virtual bool error() const;
|
||||
virtual size_t depth() { return 1; }
|
||||
|
||||
private:
|
||||
enum state {
|
||||
s_start,
|
||||
s_body,
|
||||
s_end,
|
||||
s_error
|
||||
};
|
||||
|
||||
IParserStreamReceiver &m_receiver;
|
||||
enum state m_state;
|
||||
static const std::string m_parserName;
|
||||
size_t m_parser_depth;
|
||||
};
|
||||
|
||||
#endif // __PARSER_PDF_H__
|
||||
@@ -706,6 +706,7 @@ void SerializeToLocalAndRemoteSyncBase::syncWorker()
|
||||
|
||||
MessageMetadata req_md(getLearningHost(), 80);
|
||||
req_md.insertHeader("X-Tenant-Id", agentDetails->getTenantId());
|
||||
req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
||||
bool ok = messaging->sendSyncMessageWithoutResponse(
|
||||
HTTPMethod::POST,
|
||||
"/api/sync",
|
||||
|
||||
@@ -156,6 +156,7 @@ void
|
||||
WaapTrafficTelemetrics::updateMetrics(const string &asset_id, const DecisionTelemetryData &data)
|
||||
{
|
||||
initMetrics();
|
||||
average_latency.report(data.elapsedTime);
|
||||
switch (data.method)
|
||||
{
|
||||
case POST:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
#include <boost/regex.hpp>
|
||||
#include "WaapOverrideFunctor.h"
|
||||
#include "Waf2Engine.h"
|
||||
@@ -47,14 +48,16 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const Waap::Util::C
|
||||
bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex& rx)
|
||||
{
|
||||
boost::cmatch what;
|
||||
std::string tagLower = tag;
|
||||
std::transform(tagLower.begin(), tagLower.end(), tagLower.begin(), ::tolower);
|
||||
try {
|
||||
if (tag == "url") {
|
||||
return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getUri().c_str(), what, rx);
|
||||
if (tagLower == "url") {
|
||||
return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getUriStr().c_str(), what, rx);
|
||||
}
|
||||
else if (tag == "hostname") {
|
||||
else if (tagLower == "hostname") {
|
||||
return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getHost().c_str(), what, rx);
|
||||
}
|
||||
else if (tag == "sourceidentifier") {
|
||||
else if (tagLower == "sourceidentifier") {
|
||||
return NGEN::Regex::regexMatch(
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
@@ -63,7 +66,7 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
|
||||
rx
|
||||
);
|
||||
}
|
||||
else if (tag == "keyword") {
|
||||
else if (tagLower == "keyword") {
|
||||
for (const std::string& keywordStr : waf2Transaction.getKeywordMatches()) {
|
||||
if (NGEN::Regex::regexMatch(__FILE__, __LINE__, keywordStr.c_str(), what, rx)) {
|
||||
return true;
|
||||
@@ -71,7 +74,7 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (tag == "paramname" || tag == "paramName") {
|
||||
else if (tagLower == "paramname") {
|
||||
for (const DeepParser::KeywordInfo& keywordInfo : waf2Transaction.getKeywordInfo()) {
|
||||
if (NGEN::Regex::regexMatch(__FILE__, __LINE__, keywordInfo.getName().c_str(), what, rx)) {
|
||||
return true;
|
||||
@@ -85,7 +88,7 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (tag == "paramvalue" || tag == "paramValue") {
|
||||
else if (tagLower == "paramvalue") {
|
||||
for (const DeepParser::KeywordInfo& keywordInfo : waf2Transaction.getKeywordInfo()) {
|
||||
if (NGEN::Regex::regexMatch(__FILE__, __LINE__, keywordInfo.getValue().c_str(), what, rx)) {
|
||||
return true;
|
||||
@@ -96,10 +99,10 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (tag == "paramlocation" || tag == "paramLocation") {
|
||||
else if (tagLower == "paramlocation") {
|
||||
return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getLocation().c_str(), what, rx);
|
||||
}
|
||||
else if (tag == "responsebody" || tag == "responseBody") {
|
||||
else if (tagLower == "responsebody") {
|
||||
waf2Transaction.getResponseInspectReasons().setApplyOverride(true);
|
||||
if (!waf2Transaction.getResponseBody().empty()) {
|
||||
boost::smatch matcher;
|
||||
@@ -108,6 +111,32 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (tagLower == "headername") {
|
||||
if (!waf2Transaction.checkIsHeaderOverrideScanRequired()) {
|
||||
dbgDebug(D_WAAP_OVERRIDE) << "Header name override scan is not required";
|
||||
return false;
|
||||
}
|
||||
for (auto& hdr_pair : waf2Transaction.getHdrPairs()) {
|
||||
std::string value = hdr_pair.first;
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
if(NGEN::Regex::regexMatch(__FILE__, __LINE__, value.c_str(), what, rx)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (tagLower == "headervalue") {
|
||||
if (!waf2Transaction.checkIsHeaderOverrideScanRequired()) {
|
||||
dbgDebug(D_WAAP_OVERRIDE) << "Header value override scan is not required";
|
||||
return false;
|
||||
}
|
||||
for (auto& hdr_pair : waf2Transaction.getHdrPairs()) {
|
||||
std::string value = hdr_pair.second;
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
if (NGEN::Regex::regexMatch(__FILE__, __LINE__, value.c_str(), what, rx)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error & e) {
|
||||
@@ -116,6 +145,6 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
|
||||
}
|
||||
|
||||
// Unknown tag: should not occur
|
||||
dbgWarning(D_WAAP) << "Invalid override tag:" << tag;
|
||||
dbgWarning(D_WAAP) << "Invalid override tag: " << tag;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace Waap {
|
||||
errorLimiter(false),
|
||||
rateLimiting(false),
|
||||
collectResponseForLog(false),
|
||||
applyOverride(false)
|
||||
applyOverride(false),
|
||||
triggerReport(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -39,11 +40,12 @@ namespace Waap {
|
||||
" RateLimiting=" << rateLimiting <<
|
||||
" ErrorLimiter=" << errorLimiter <<
|
||||
" collectResponseForLog=" << collectResponseForLog <<
|
||||
" applyOverride=" << applyOverride;
|
||||
" applyOverride=" << applyOverride <<
|
||||
" triggerReport=" << triggerReport;
|
||||
|
||||
return
|
||||
openRedirect || errorDisclosure || rateLimiting || errorLimiter ||
|
||||
collectResponseForLog || applyOverride;
|
||||
collectResponseForLog || applyOverride || triggerReport;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -91,6 +93,14 @@ namespace Waap {
|
||||
applyOverride = flag;
|
||||
}
|
||||
|
||||
void
|
||||
ResponseInspectReasons::setTriggerReport(bool flag)
|
||||
{
|
||||
dbgTrace(D_WAAP) << "Change ResponseInspectReasons(setTriggerReport) " << triggerReport << " to " <<
|
||||
flag;
|
||||
triggerReport = flag;
|
||||
}
|
||||
|
||||
bool
|
||||
ResponseInspectReasons::getApplyOverride(void)
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
void setErrorLimiter(bool flag);
|
||||
void setCollectResponseForLog(bool flag);
|
||||
void setApplyOverride(bool flag);
|
||||
void setTriggerReport(bool flag);
|
||||
|
||||
bool getApplyOverride(void);
|
||||
private:
|
||||
@@ -34,6 +35,7 @@ private:
|
||||
bool rateLimiting;
|
||||
bool collectResponseForLog;
|
||||
bool applyOverride;
|
||||
bool triggerReport;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -56,8 +56,10 @@ USE_DEBUG_FLAG(D_WAAP);
|
||||
USE_DEBUG_FLAG(D_WAAP_ULIMITS);
|
||||
USE_DEBUG_FLAG(D_WAAP_BOT_PROTECTION);
|
||||
USE_DEBUG_FLAG(D_OA_SCHEMA_UPDATER);
|
||||
USE_DEBUG_FLAG(D_WAAP_HEADERS);
|
||||
|
||||
using namespace ReportIS;
|
||||
using namespace std;
|
||||
|
||||
#define MAX_REQUEST_BODY_SIZE (2*1024)
|
||||
#define MAX_RESPONSE_BODY_SIZE (2*1024)
|
||||
@@ -89,6 +91,9 @@ void Waf2Transaction::start_response(int response_status, int http_version)
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] start_response(response_status=" << response_status
|
||||
<< "," << " http_version=" << http_version << ")";
|
||||
m_responseStatus = response_status;
|
||||
if (m_triggerReport) {
|
||||
m_responseInspectReasons.setTriggerReport(false);
|
||||
}
|
||||
|
||||
if(m_responseStatus == 404)
|
||||
{
|
||||
@@ -233,6 +238,12 @@ void Waf2Transaction::end_response_body()
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] end_response_body";
|
||||
}
|
||||
|
||||
const std::string &
|
||||
Waf2Transaction::getResponseBody()
|
||||
{
|
||||
return m_response_body;
|
||||
}
|
||||
|
||||
void Waf2Transaction::scanErrDisclosureBuffer()
|
||||
{
|
||||
if (m_responseStatus >= 400 && m_responseStatus <= 599) {
|
||||
@@ -302,19 +313,25 @@ Waf2Transaction::Waf2Transaction() :
|
||||
m_deepParser(m_pWaapAssetState, m_scanner, this),
|
||||
m_deepParserReceiver(m_deepParser),
|
||||
m_scanResult(NULL),
|
||||
m_response_body(),
|
||||
m_request_body_bytes_received(0),
|
||||
m_response_body_bytes_received(0),
|
||||
m_processedUri(false),
|
||||
m_processedHeaders(false),
|
||||
m_isHeaderOverrideScanRequired(false),
|
||||
m_isScanningRequired(false),
|
||||
m_responseStatus(0),
|
||||
m_responseInspectReasons(),
|
||||
m_responseInjectReasons(),
|
||||
m_index(-1),
|
||||
m_triggerLog(),
|
||||
m_triggerReport(false),
|
||||
is_schema_validation(false),
|
||||
m_waf2TransactionFlags()
|
||||
{}
|
||||
{
|
||||
I_TimeGet *timeGet = Singleton::Consume<I_TimeGet>::by<Waf2Transaction>();
|
||||
m_entry_time = chrono::duration_cast<chrono::milliseconds>(timeGet->getMonotonicTime());
|
||||
}
|
||||
|
||||
Waf2Transaction::Waf2Transaction(std::shared_ptr<WaapAssetState> pWaapAssetState) :
|
||||
TableOpaqueSerialize<Waf2Transaction>(this),
|
||||
@@ -334,19 +351,25 @@ Waf2Transaction::Waf2Transaction(std::shared_ptr<WaapAssetState> pWaapAssetState
|
||||
m_deepParser(m_pWaapAssetState, m_scanner, this),
|
||||
m_deepParserReceiver(m_deepParser),
|
||||
m_scanResult(NULL),
|
||||
m_response_body(),
|
||||
m_request_body_bytes_received(0),
|
||||
m_response_body_bytes_received(0),
|
||||
m_processedUri(false),
|
||||
m_processedHeaders(false),
|
||||
m_isHeaderOverrideScanRequired(false),
|
||||
m_isScanningRequired(false),
|
||||
m_responseStatus(0),
|
||||
m_responseInspectReasons(),
|
||||
m_responseInjectReasons(),
|
||||
m_index(-1),
|
||||
m_triggerLog(),
|
||||
m_triggerReport(false),
|
||||
is_schema_validation(false),
|
||||
m_waf2TransactionFlags()
|
||||
{}
|
||||
{
|
||||
I_TimeGet *timeGet = Singleton::Consume<I_TimeGet>::by<Waf2Transaction>();
|
||||
m_entry_time = chrono::duration_cast<chrono::milliseconds>(timeGet->getMonotonicTime());
|
||||
}
|
||||
|
||||
Waf2Transaction::~Waf2Transaction() {
|
||||
dbgTrace(D_WAAP) << "Waf2Transaction::~Waf2Transaction: deleting m_requestBodyParser";
|
||||
@@ -362,6 +385,8 @@ HeaderType Waf2Transaction::detectHeaderType(const char* name, int name_len) {
|
||||
static const char content_type[] = "content-Type";
|
||||
static const char cookie[] = "cookie";
|
||||
static const char referer[] = "referer";
|
||||
static const char authorization[] = "authorization";
|
||||
dbgTrace(D_WAAP_HEADERS) << "Detecting header type for header >>>" << std::string(name, name_len) << "<<<";
|
||||
|
||||
if (memcaseinsensitivecmp(name, name_len, host, sizeof(host) - 1)) {
|
||||
return HeaderType::HOST_HEADER;
|
||||
@@ -378,6 +403,9 @@ HeaderType Waf2Transaction::detectHeaderType(const char* name, int name_len) {
|
||||
if (memcaseinsensitivecmp(name, name_len, referer, sizeof(referer) - 1)) {
|
||||
return HeaderType::REFERER_HEADER;
|
||||
}
|
||||
if (memcaseinsensitivecmp(name, name_len, authorization, sizeof(authorization) - 1)) {
|
||||
return HeaderType::AUTHORIZATION_HEADER;
|
||||
}
|
||||
return UNKNOWN_HEADER;
|
||||
}
|
||||
|
||||
@@ -422,37 +450,100 @@ HeaderType Waf2Transaction::checkCleanHeader(const char* name, int name_len, con
|
||||
return CLEAN_HEADER;
|
||||
}
|
||||
}
|
||||
|
||||
static const std::string authorization("authorization");
|
||||
if (memcaseinsensitivecmp(name, name_len, authorization.data(), authorization.size())) {
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] special header '" << std::string(name, name_len) <<
|
||||
"' - detect base64 to determine cleanliness ...";
|
||||
|
||||
std::string result;
|
||||
int decodedCount = 0;
|
||||
int deletedCount = 0;
|
||||
|
||||
std::string v(value, value_len);
|
||||
boost::algorithm::to_lower(v);
|
||||
const std::string negotiate("negotiate ");
|
||||
|
||||
if (boost::algorithm::starts_with(v, negotiate)) {
|
||||
v = v.substr(negotiate.size(), v.size() - negotiate.size());
|
||||
|
||||
// Detect potential base64 match after the "Negotiate " prefix
|
||||
Waap::Util::b64Decode(v, b64DecodeChunk, decodedCount, deletedCount, result);
|
||||
if (result.empty() && (deletedCount + decodedCount == 1)) {
|
||||
// Decoded 1 base64 chunk and nothing left behind it
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] special header '" <<
|
||||
std::string(name, name_len) << " is clean";
|
||||
return CLEAN_HEADER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return UNKNOWN_HEADER;
|
||||
}
|
||||
|
||||
void Waf2Transaction::parseAuthorization(const char* value, int value_len, const std::string &header_name)
|
||||
{
|
||||
#ifdef NO_HEADERS_SCAN
|
||||
return;
|
||||
#endif
|
||||
static const std::string authorization("authorization");
|
||||
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this
|
||||
<< "] special header '" << header_name;
|
||||
|
||||
std::string result;
|
||||
std::string v(value, value_len);
|
||||
int decodedCount;
|
||||
int deletedCount;
|
||||
static const char *bearer = "bearer ";
|
||||
static const std::string bearer_str(bearer);
|
||||
if (memcaseinsensitivecmp(value, sizeof(bearer) - 1, bearer, sizeof(bearer) - 1)) {
|
||||
dbgTrace(D_WAAP_HEADERS) << "Checking JWT chunk for alg = none" << v;
|
||||
// parse buffer v till first dot,
|
||||
// convert this chunk from base 64 to json string and get value for "alg" key
|
||||
// if alg == "none" then this is JWT with no signature and we should block it
|
||||
// if alg != "none" then this is JWT with signature and we should not block it
|
||||
char* p = (char*)v.c_str() + bearer_str.size();
|
||||
char* p1 = strchr(p, '.');
|
||||
if (p1 != NULL) {
|
||||
*p1 = '\0';
|
||||
std::string header(p);
|
||||
alignBase64Chunk(header);
|
||||
Waap::Util::b64Decode(header, b64DecodeChunk, decodedCount, deletedCount, result);
|
||||
if (!result.empty()) {
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] special header '" << header_name
|
||||
<< " base64 encoded for JWT alg testing";
|
||||
// parse JSON string and get value for "alg" key and check its value to be equal to "none"
|
||||
// if alg == "none" then this is JWT with no signature and we should block it
|
||||
boost::algorithm::to_lower(result);
|
||||
static bool err = false;
|
||||
static const SingleRegex invalid_jwt_alg_re(
|
||||
"\"alg\"\\s*:\\s*\"none\"",
|
||||
err,
|
||||
"invalid_jwt_alg_"
|
||||
);
|
||||
if (invalid_jwt_alg_re.hasMatch(result)) {
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] special header '" << header_name
|
||||
<< " bad JWT algotitm detected, blocking";
|
||||
Waf2ScanResult new_res = Waf2ScanResult();
|
||||
new_res.location = "header";
|
||||
new_res.param_name = header_name;
|
||||
new_res.unescaped_line = header_name + ": " + result;
|
||||
new_res.score = 9.0;
|
||||
new_res.keyword_matches.push_back("alg:none");
|
||||
new_res.scoreArray.push_back(9.0);
|
||||
new_res.attack_types.insert("JWT");
|
||||
if (m_scanResult != NULL) {
|
||||
dbgTrace(D_WAAP_HEADERS) << "LastScanResult = " << m_scanResult;
|
||||
m_scanResult->mergeFrom(new_res);
|
||||
} else {
|
||||
dbgTrace(D_WAAP_HEADERS) << "LastScanResult is NULL";
|
||||
m_scanResult = new Waf2ScanResult(new_res);
|
||||
}
|
||||
return;
|
||||
}
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] special header '" << header_name
|
||||
<< " clean JWT algotitm detected";
|
||||
return;
|
||||
} else {
|
||||
parseGenericHeaderValue(header_name, value, value_len);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static const char *negotiate = "negotiate ";
|
||||
static const std::string negotiate_str(negotiate);
|
||||
if (memcaseinsensitivecmp(value, sizeof(negotiate) - 1, negotiate, sizeof(negotiate) - 1)) {
|
||||
v = v.substr(negotiate_str.size(), v.size() - negotiate_str.size());
|
||||
|
||||
// Detect potential base64 match after the "Negotiate " prefix
|
||||
alignBase64Chunk(v);
|
||||
Waap::Util::b64Decode(v, b64DecodeChunk, decodedCount, deletedCount, result);
|
||||
if (result.empty() && (deletedCount + decodedCount == 1)) {
|
||||
// Decoded 1 base64 chunk and nothing left behind it
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] special header '" << header_name
|
||||
<< " is clean - clean base64 for negotiate";
|
||||
return;
|
||||
} else {
|
||||
parseGenericHeaderValue(header_name, value, value_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Methods below are callbacks that are called during HTTP transaction processing by the front-end server/proxy
|
||||
void Waf2Transaction::start() {
|
||||
dbgTrace(D_WAAP) << "[Waf2Transaction::start():" << this << "] start";
|
||||
@@ -744,14 +835,14 @@ void Waf2Transaction::parseContentType(const char* value, int value_len)
|
||||
ctp.push(value, value_len);
|
||||
ctp.finish();
|
||||
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] ctp detected content type: '" <<
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] ctp detected content type: '" <<
|
||||
ctp.contentTypeDetected.c_str() << "'";
|
||||
// The above fills m_contentTypeDetected
|
||||
m_contentType = Waap::Util::detectContentType(ctp.contentTypeDetected.c_str());
|
||||
|
||||
// extract boundary string required for parsing multipart-form-data stream
|
||||
if (m_contentType == Waap::Util::CONTENT_TYPE_MULTIPART_FORM) {
|
||||
dbgTrace(D_WAAP) << "content_type detected: " << Waap::Util::getContentTypeStr(m_contentType) <<
|
||||
dbgTrace(D_WAAP_HEADERS) << "content_type detected: " << Waap::Util::getContentTypeStr(m_contentType) <<
|
||||
"; boundary='" << ctp.boundaryFound.c_str() << "'";
|
||||
m_deepParser.setMultipartBoundary(ctp.boundaryFound);
|
||||
}
|
||||
@@ -773,7 +864,7 @@ void Waf2Transaction::parseCookie(const char* value, int value_len)
|
||||
#endif
|
||||
|
||||
if (value_len > 0) {
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] scanning the cookie value";
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] scanning the cookie value";
|
||||
m_deepParser.m_key.push("cookie", 6);
|
||||
ParserUrlEncode cookieValueParser(m_deepParserReceiver, 0, ';');
|
||||
cookieValueParser.push(value, value_len);
|
||||
@@ -788,7 +879,7 @@ void Waf2Transaction::parseReferer(const char* value, int value_len)
|
||||
#ifdef NO_HEADERS_SCAN
|
||||
return;
|
||||
#endif
|
||||
dbgTrace(D_WAAP) << "Parsed Referer. Referer URI: " << m_uriReferer;
|
||||
dbgTrace(D_WAAP_HEADERS) << "Parsed Referer. Referer URI: " << m_uriReferer;
|
||||
|
||||
std::string referer(value, value_len);
|
||||
std::vector<RegexMatch> regex_matches;
|
||||
@@ -815,7 +906,7 @@ void Waf2Transaction::parseUnknownHeaderName(const char* name, int name_len)
|
||||
// Apply signatures on all other, header names, unless they are considered "good" ones to skip scanning them.
|
||||
if (name_len &&
|
||||
!m_pWaapAssetState->getSignatures()->good_header_name_re.hasMatch(std::string(name, name_len))) {
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] scanning the header name";
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] scanning the header name";
|
||||
m_deepParser.m_key.push("header", 6);
|
||||
ParserRaw headerNameParser(m_deepParserReceiver, 0, std::string(name, name_len));
|
||||
headerNameParser.push(name, name_len);
|
||||
@@ -834,7 +925,7 @@ void Waf2Transaction::parseGenericHeaderValue(const std::string &headerName, con
|
||||
return;
|
||||
}
|
||||
|
||||
dbgTrace(D_WAAP) << "[transaction:" << this << "] scanning the header value";
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] scanning the header value";
|
||||
m_deepParser.m_key.push("header", 6);
|
||||
ParserRaw headerValueParser(m_deepParserReceiver, 0, headerName);
|
||||
headerValueParser.push(value, value_len);
|
||||
@@ -844,11 +935,11 @@ void Waf2Transaction::parseGenericHeaderValue(const std::string &headerName, con
|
||||
};
|
||||
|
||||
// Scan relevant headers to detect attacks inside them
|
||||
void Waf2Transaction::scanSpecificHeder(const char* name, int name_len, const char* value, int value_len)
|
||||
void Waf2Transaction::scanSpecificHeader(const char* name, int name_len, const char* value, int value_len)
|
||||
{
|
||||
HeaderType header_t = detectHeaderType(name, name_len);
|
||||
std::string headerName = std::string(name, name_len);
|
||||
|
||||
dbgTrace(D_WAAP_HEADERS) << "Processing the header " << headerName;
|
||||
switch (header_t)
|
||||
{
|
||||
case HeaderType::COOKIE_HEADER:
|
||||
@@ -857,6 +948,9 @@ void Waf2Transaction::scanSpecificHeder(const char* name, int name_len, const ch
|
||||
case HeaderType::REFERER_HEADER:
|
||||
parseReferer(value, value_len);
|
||||
break;
|
||||
case HeaderType::AUTHORIZATION_HEADER:
|
||||
parseAuthorization(value, value_len, headerName);
|
||||
break;
|
||||
case HeaderType::UNKNOWN_HEADER: {
|
||||
HeaderType headerType = checkCleanHeader(name, name_len, value, value_len);
|
||||
if(headerType == HeaderType::CLEAN_HEADER) {
|
||||
@@ -954,7 +1048,7 @@ void Waf2Transaction::scanHeaders()
|
||||
// Scan relevant headers for attacks
|
||||
for (auto it = hdrs_map.begin(); it != hdrs_map.end(); ++it)
|
||||
{
|
||||
scanSpecificHeder(it->first.c_str(), it->first.size(),
|
||||
scanSpecificHeader(it->first.c_str(), it->first.size(),
|
||||
it->second.c_str(), it->second.size());
|
||||
}
|
||||
}
|
||||
@@ -1171,6 +1265,12 @@ void Waf2Transaction::end_request() {
|
||||
// Enable response headers processing if response scanning is enabled in policy
|
||||
auto errorDisclosurePolicy = m_siteConfig ? m_siteConfig->get_ErrorDisclosurePolicy() : NULL;
|
||||
m_responseInspectReasons.setErrorDisclosure(errorDisclosurePolicy && errorDisclosurePolicy->enable);
|
||||
|
||||
auto triggerPolicy = m_siteConfig ? m_siteConfig->get_TriggerPolicy() : NULL;
|
||||
if (isTriggerReportExists(triggerPolicy)) {
|
||||
m_responseInspectReasons.setTriggerReport(true);
|
||||
dbgTrace(D_WAAP) << "setTriggerReport(true)";
|
||||
}
|
||||
}
|
||||
|
||||
void Waf2Transaction::extractEnvSourceIdentifier()
|
||||
@@ -1393,6 +1493,7 @@ Waf2Transaction::decideAfterHeaders()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_isHeaderOverrideScanRequired = true;
|
||||
m_overrideState = getOverrideState(sitePolicy);
|
||||
|
||||
// Select scores pool by location (but use forced pool when forced)
|
||||
@@ -1648,6 +1749,12 @@ Waf2Transaction::sendLog()
|
||||
const auto& autonomousSecurityDecision = std::dynamic_pointer_cast<AutonomousSecurityDecision>(
|
||||
m_waapDecision.getDecision(AUTONOMOUS_SECURITY_DECISION));
|
||||
|
||||
I_TimeGet *timeGet = Singleton::Consume<I_TimeGet>::by<Waf2Transaction>();
|
||||
auto finish = timeGet->getMonotonicTime();
|
||||
auto diff = chrono::duration_cast<chrono::milliseconds>(finish) - m_entry_time;
|
||||
telemetryData.elapsedTime = diff.count();
|
||||
dbgTrace(D_WAAP) << "latency updated, time: " << diff.count() << "ms";
|
||||
|
||||
if (m_methodStr == "POST") {
|
||||
telemetryData.method = POST;
|
||||
} else if (m_methodStr == "GET") {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "i_transaction.h"
|
||||
#include "i_waap_telemetry.h"
|
||||
#include "i_deepAnalyzer.h"
|
||||
#include "i_time_get.h"
|
||||
#include "table_opaque.h"
|
||||
#include "WaapResponseInspectReasons.h"
|
||||
#include "WaapResponseInjectReasons.h"
|
||||
@@ -45,6 +46,7 @@
|
||||
#include "WaapOpenRedirectPolicy.h"
|
||||
#include "WaapScanner.h"
|
||||
#include "singleton.h"
|
||||
#include "OASchemaUpdaterConfConstant.h"
|
||||
|
||||
struct DecisionTelemetryData;
|
||||
class Waf2Transaction;
|
||||
@@ -60,6 +62,7 @@ class Waf2Transaction :
|
||||
public Singleton::Consume<I_Table>,
|
||||
private boost::noncopyable,
|
||||
Singleton::Consume<I_AgentDetails>,
|
||||
Singleton::Consume<I_TimeGet>,
|
||||
Singleton::Consume<I_Environment>
|
||||
{
|
||||
public:
|
||||
@@ -76,6 +79,7 @@ public:
|
||||
void set_host(const char *host);
|
||||
|
||||
// getters
|
||||
uint64_t getElapsedTime() const;
|
||||
const std::string& getRemoteAddr() const;
|
||||
virtual const std::string getUri() const;
|
||||
const std::string getUriStr() const;
|
||||
@@ -143,6 +147,7 @@ public:
|
||||
void start_response_body();
|
||||
void add_response_body_chunk(const char* data, int data_len);
|
||||
void end_response_body();
|
||||
const std::string & getResponseBody();
|
||||
void end_response();
|
||||
void extractEnvSourceIdentifier();
|
||||
void finish();
|
||||
@@ -212,19 +217,21 @@ public:
|
||||
}
|
||||
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
bool reportScanResult(const Waf2ScanResult &res);
|
||||
bool shouldIgnoreOverride(const Waf2ScanResult &res);
|
||||
Waap::OpenRedirect::State &getOpenRedirectState() { return m_openRedirectState; }
|
||||
IWaapConfig* getSiteConfig() { return m_siteConfig; }
|
||||
void addNote(const std::string ¬e) { m_notes.push_back(note); }
|
||||
const std::string &getResponseBody(void) const { return m_response_body; }
|
||||
Waap::ResponseInspectReasons &getResponseInspectReasons(void) { return m_responseInspectReasons; }
|
||||
// LCOV_EXCL_START Reason: This function is tested in system tests
|
||||
bool checkIsHeaderOverrideScanRequired();
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
private:
|
||||
int finalizeDecision(IWaapConfig *sitePolicy, bool shouldBlock);
|
||||
const std::shared_ptr<Waap::Trigger::Log> getTriggerLog(const std::shared_ptr<Waap::Trigger::Policy>&
|
||||
triggerPolicy) const;
|
||||
bool isTriggerReportExists(const std::shared_ptr<Waap::Trigger::Policy> &triggerPolicy);
|
||||
void sendAutonomousSecurityLog(
|
||||
const std::shared_ptr<Waap::Trigger::Log>& triggerLog,
|
||||
bool shouldBlock,
|
||||
@@ -261,15 +268,17 @@ private:
|
||||
void parseContentType(const char* value, int value_len);
|
||||
void parseCookie(const char* value, int value_len);
|
||||
void parseReferer(const char* value, int value_len);
|
||||
void parseAuthorization(const char* value, int value_len, const std::string &header_name);
|
||||
void parseUnknownHeaderName(const char* name, int name_len);
|
||||
void parseGenericHeaderValue(const std::string &headerName, const char* value, int value_len);
|
||||
void scanSpecificHeder(const char* name, int name_len, const char* value, int value_len);
|
||||
void scanSpecificHeader(const char* name, int name_len, const char* value, int value_len);
|
||||
void detectSpecificHeader(const char* name, int name_len, const char* value, int value_len);
|
||||
void detectHeaders();
|
||||
void scanHeaders();
|
||||
void clearRequestParserState();
|
||||
void scanErrDisclosureBuffer();
|
||||
|
||||
std::chrono::milliseconds m_entry_time;
|
||||
std::shared_ptr<WaapAssetState> m_pWaapAssetState;
|
||||
bool m_ignoreScore; // override the scoring filter and (effectively) take the last suspicious parameter,
|
||||
// instead of the one with highest score that is > SCORE_THRESHOLD
|
||||
@@ -334,6 +343,7 @@ private:
|
||||
|
||||
bool m_processedUri;
|
||||
bool m_processedHeaders;
|
||||
bool m_isHeaderOverrideScanRequired;
|
||||
bool m_isScanningRequired;
|
||||
int m_responseStatus;
|
||||
Waap::ResponseInspectReasons m_responseInspectReasons;
|
||||
@@ -345,6 +355,7 @@ private:
|
||||
|
||||
// Cached pointer to const triggerLog (hence mutable)
|
||||
mutable std::shared_ptr<Waap::Trigger::Log> m_triggerLog;
|
||||
bool m_triggerReport;
|
||||
bool is_schema_validation = false;
|
||||
Waf2TransactionFlags m_waf2TransactionFlags;
|
||||
};
|
||||
|
||||
@@ -551,6 +551,11 @@ const std::set<std::string> Waf2Transaction::getFoundPatterns() const
|
||||
return m_found_patterns;
|
||||
}
|
||||
|
||||
bool Waf2Transaction::checkIsHeaderOverrideScanRequired()
|
||||
{
|
||||
return m_isHeaderOverrideScanRequired;
|
||||
}
|
||||
|
||||
Waap::Override::State Waf2Transaction::getOverrideState(IWaapConfig* sitePolicy)
|
||||
{
|
||||
Waap::Override::State overrideState;
|
||||
@@ -566,6 +571,7 @@ Waap::Override::State Waf2Transaction::getOverrideState(IWaapConfig* sitePolicy)
|
||||
if (overridePolicy) { // later we will run response overrides
|
||||
overrideStateResponse.applyOverride(*overridePolicy, WaapOverrideFunctor(*this), m_matchedOverrideIds, false);
|
||||
}
|
||||
m_isHeaderOverrideScanRequired = false;
|
||||
return overrideStateResponse;
|
||||
}
|
||||
|
||||
@@ -592,6 +598,23 @@ const std::shared_ptr<Waap::Trigger::Log> Waf2Transaction::getTriggerLog(const s
|
||||
return m_triggerLog;
|
||||
}
|
||||
|
||||
bool Waf2Transaction::isTriggerReportExists(const std::shared_ptr<
|
||||
Waap::Trigger::Policy> &triggerPolicy)
|
||||
{
|
||||
if (!triggerPolicy) {
|
||||
return false;
|
||||
}
|
||||
if (m_triggerReport) {
|
||||
return m_triggerReport;
|
||||
}
|
||||
for (const Waap::Trigger::Trigger &trigger : triggerPolicy->triggers) {
|
||||
if (trigger.triggerType == "report") {
|
||||
return m_triggerReport = true;
|
||||
}
|
||||
}
|
||||
return m_triggerReport;
|
||||
}
|
||||
|
||||
ReportIS::Severity Waf2Transaction::computeEventSeverityFromDecision() const
|
||||
{
|
||||
DecisionType type = m_waapDecision.getHighestPriorityDecisionToLog();
|
||||
|
||||
@@ -732,6 +732,13 @@ inline void replaceAll(std::string& str, const std::string& from, const std::str
|
||||
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
||||
}
|
||||
}
|
||||
inline void alignBase64Chunk (std::string &chunk)
|
||||
{
|
||||
size_t len = chunk.length() % 4;
|
||||
if (len >= 2) {
|
||||
chunk.append(4-len, '=');
|
||||
}
|
||||
}
|
||||
|
||||
// Count items in v that are not in ignored_set
|
||||
inline size_t countNotInSet(const std::vector<std::string> &v, const std::set<std::string> &ignored_set) {
|
||||
|
||||
@@ -170,11 +170,15 @@ WaapComponent::Impl::respond(const NewHttpTransactionEvent &event)
|
||||
|
||||
waf2Transaction.start();
|
||||
|
||||
char sourceIpStr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(event.getSourceIP()), sourceIpStr, INET_ADDRSTRLEN);
|
||||
|
||||
char listeningIpStr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(event.getListeningIP()), listeningIpStr, INET_ADDRSTRLEN);
|
||||
char sourceIpStr[INET6_ADDRSTRLEN];
|
||||
char listeningIpStr[INET6_ADDRSTRLEN];
|
||||
if (event.getSourceIP().getType() == IPType::V4) {
|
||||
inet_ntop(AF_INET, &(event.getSourceIP()), sourceIpStr, INET6_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, &(event.getListeningIP()), listeningIpStr, INET6_ADDRSTRLEN);
|
||||
} else {
|
||||
inet_ntop(AF_INET6, &(event.getSourceIP()), sourceIpStr, INET6_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET6, &(event.getListeningIP()), listeningIpStr, INET6_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
// Set envelope data
|
||||
waf2Transaction.set_transaction_remote(sourceIpStr, event.getSourcePort());
|
||||
@@ -515,7 +519,6 @@ WaapComponent::Impl::respond(const HttpResponseBodyEvent &event)
|
||||
|
||||
dbgTrace(D_WAAP) << "HttpBodyResponse";
|
||||
|
||||
|
||||
// Push the response data chunk to the waf2 engine
|
||||
const char *dataBuf = (const char*)event.getData().data();
|
||||
size_t dataBufLen = event.getData().size();
|
||||
|
||||
Reference in New Issue
Block a user