Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
v3.0.15 - TBD
---------------------

- feat: Regex pattern for variable key in ctl:ruleRemoveTargetById and
ctl:ruleRemoveTargetByTag (#3505)
[PR #3526 - @etiennemunnich]

v3.0.14 - 2025-Feb-25
---------------------

Expand Down
56 changes: 56 additions & 0 deletions headers/modsecurity/rule_remove_target_entry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* If any of the files related to licensing are missing or if you have any
* other questions related to licensing please contact Trustwave Holdings, Inc.
* directly using the email address [email protected].
*
*/

#ifndef HEADERS_MODSECURITY_RULE_REMOVE_TARGET_ENTRY_H_
#define HEADERS_MODSECURITY_RULE_REMOVE_TARGET_ENTRY_H_

#include <memory>
#include <string>

namespace modsecurity {

namespace Utils {
class Regex;
}

/**
* Shared target-matching logic for ctl:ruleRemoveTarget{ById,ByTag}.
* Supports literal target (e.g. ARGS:pwd) or regex (e.g. ARGS:/^json\.\d+\.JobDescription$/).
* Regex is compiled at config load time.
*/
struct RuleRemoveTargetSpec {
std::string literal;
std::shared_ptr<Utils::Regex> regex;

bool matchesKeyWithCollection(const std::string &key,
const std::string &keyWithCollection) const;
bool matchesFullName(const std::string &fullName) const;
};


struct RuleRemoveTargetByIdEntry {
int id;
RuleRemoveTargetSpec target;
};


struct RuleRemoveTargetByTagEntry {
std::string tag;
RuleRemoveTargetSpec target;
};

} // namespace modsecurity

#endif // HEADERS_MODSECURITY_RULE_REMOVE_TARGET_ENTRY_H_
7 changes: 5 additions & 2 deletions headers/modsecurity/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ typedef struct Rules_t RulesSet;
#include "modsecurity/variable_origin.h"
#include "modsecurity/anchored_set_variable_translation_proxy.h"
#include "modsecurity/audit_log.h"
#ifdef __cplusplus
#include "modsecurity/rule_remove_target_entry.h"
#endif


#ifndef NO_LOGS
Expand Down Expand Up @@ -520,12 +523,12 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
/**
*
*/
std::list< std::pair<std::string, std::string> > m_ruleRemoveTargetByTag;
std::list<RuleRemoveTargetByTagEntry> m_ruleRemoveTargetByTag;

/**
*
*/
std::list< std::pair<int, std::string> > m_ruleRemoveTargetById;
std::list<RuleRemoveTargetByIdEntry> m_ruleRemoveTargetById;

/**
*
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pkginclude_HEADERS = \
../headers/modsecurity/rule_unconditional.h \
../headers/modsecurity/rule_with_actions.h \
../headers/modsecurity/rule_with_operator.h \
../headers/modsecurity/rule_remove_target_entry.h \
../headers/modsecurity/rules.h \
../headers/modsecurity/rule_message.h \
../headers/modsecurity/rules_set.h \
Expand Down Expand Up @@ -274,6 +275,7 @@ libmodsecurity_la_SOURCES = \
rule_unconditional.cc \
rule_with_actions.cc \
rule_with_operator.cc \
rule_remove_target_entry.cc \
rule_message.cc \
rule_script.cc \
unique_id.cc \
Expand Down
30 changes: 28 additions & 2 deletions src/actions/ctl/rule_remove_target_by_id.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
#include <string>
#include <vector>
#include <utility>
#include <memory>

#include "modsecurity/transaction.h"
#include "modsecurity/rule_remove_target_entry.h"
#include "src/utils/string.h"
#include "src/utils/regex.h"


namespace modsecurity {
Expand All @@ -48,12 +51,35 @@

m_target = param[1];

// Detect regex format: COLLECTION:/pattern/ (e.g. ARGS:/mixpanel$/)
if (m_target.size() >= 4) {
size_t colon = m_target.find(':');
if (colon != std::string::npos && colon + 2 < m_target.size() &&
m_target[colon + 1] == '/' && m_target[m_target.size() - 1] == '/') {
size_t pattern_start = colon + 2;
size_t pattern_end = m_target.size() - 1;
if (pattern_end > pattern_start) {
std::string pattern = m_target.substr(pattern_start,
pattern_end - pattern_start);
m_regex = std::make_shared<Utils::Regex>(pattern, true);
if (m_regex->hasError()) {

Check failure on line 65 in src/actions/ctl/rule_remove_target_by_id.cc

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=owasp-modsecurity_ModSecurity&issues=AZ02d7wOPAYx8a-QfLig&open=AZ02d7wOPAYx8a-QfLig&pullRequest=3526
error->assign("Invalid regex in ctl:ruleRemoveTargetById: " +
m_target);
return false;
}
}
}
}

return true;
}

bool RuleRemoveTargetById::evaluate(RuleWithActions *rule, Transaction *transaction) {
transaction->m_ruleRemoveTargetById.push_back(
std::make_pair(m_id, m_target));
RuleRemoveTargetByIdEntry entry;
entry.id = m_id;
entry.target.literal = m_target;
entry.target.regex = m_regex;
transaction->m_ruleRemoveTargetById.push_back(std::move(entry));
return true;
}

Expand Down
3 changes: 3 additions & 0 deletions src/actions/ctl/rule_remove_target_by_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
*
*/

#include <memory>
#include <string>

#include "modsecurity/actions/action.h"
#include "modsecurity/transaction.h"
#include "src/utils/regex.h"


#ifndef SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_ID_H_
Expand All @@ -39,6 +41,7 @@ class RuleRemoveTargetById : public Action {

int m_id;
std::string m_target;
std::shared_ptr<Utils::Regex> m_regex; // pre-compiled at config load
};


Expand Down
29 changes: 27 additions & 2 deletions src/actions/ctl/rule_remove_target_by_tag.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
#include <string>
#include <vector>
#include <utility>
#include <memory>

#include "modsecurity/transaction.h"
#include "modsecurity/rule_remove_target_entry.h"
#include "src/utils/string.h"
#include "src/utils/regex.h"


namespace modsecurity {
Expand All @@ -41,12 +44,34 @@
m_tag = param[0];
m_target = param[1];

if (m_target.size() >= 4) {
size_t colon = m_target.find(':');
if (colon != std::string::npos && colon + 2 < m_target.size() &&
m_target[colon + 1] == '/' && m_target[m_target.size() - 1] == '/') {
size_t pattern_start = colon + 2;
size_t pattern_end = m_target.size() - 1;
if (pattern_end > pattern_start) {
std::string pattern = m_target.substr(pattern_start,
pattern_end - pattern_start);
m_regex = std::make_shared<Utils::Regex>(pattern, true);
if (m_regex->hasError()) {

Check failure on line 57 in src/actions/ctl/rule_remove_target_by_tag.cc

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=owasp-modsecurity_ModSecurity&issues=AZ02d7v-PAYx8a-QfLif&open=AZ02d7v-PAYx8a-QfLif&pullRequest=3526
error->assign("Invalid regex in ctl:ruleRemoveTargetByTag: " +
m_target);
return false;
}
}
}
}

return true;
}

bool RuleRemoveTargetByTag::evaluate(RuleWithActions *rule, Transaction *transaction) {
transaction->m_ruleRemoveTargetByTag.push_back(
std::make_pair(m_tag, m_target));
RuleRemoveTargetByTagEntry entry;
entry.tag = m_tag;
entry.target.literal = m_target;
entry.target.regex = m_regex;
transaction->m_ruleRemoveTargetByTag.push_back(std::move(entry));
return true;
}

Expand Down
3 changes: 3 additions & 0 deletions src/actions/ctl/rule_remove_target_by_tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
*
*/

#include <memory>
#include <string>

#include "modsecurity/actions/action.h"
#include "modsecurity/transaction.h"
#include "src/utils/regex.h"


#ifndef SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_TAG_H_
Expand All @@ -37,6 +39,7 @@ class RuleRemoveTargetByTag : public Action {

std::string m_tag;
std::string m_target;
std::shared_ptr<Utils::Regex> m_regex;
};


Expand Down
Loading
Loading