mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 13:56:01 +03:00
Add proper error handling to @rx operator
This commit is contained in:
parent
9c3c4dc587
commit
9e32945bc4
@ -29,7 +29,12 @@ namespace operators {
|
|||||||
|
|
||||||
bool Rx::init(const std::string &arg, std::string *error) {
|
bool Rx::init(const std::string &arg, std::string *error) {
|
||||||
if (m_string->m_containsMacro == false) {
|
if (m_string->m_containsMacro == false) {
|
||||||
|
std::string regex_error;
|
||||||
m_re = new Regex(m_param);
|
m_re = new Regex(m_param);
|
||||||
|
if (!m_re->ok(®ex_error)) {
|
||||||
|
*error = "Failed to compile regular expression " + m_re->getPattern() + ": " + regex_error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -47,6 +52,14 @@ bool Rx::evaluate(Transaction *transaction, Rule *rule,
|
|||||||
if (m_string->m_containsMacro) {
|
if (m_string->m_containsMacro) {
|
||||||
std::string eparam(m_string->evaluate(transaction));
|
std::string eparam(m_string->evaluate(transaction));
|
||||||
re = new Regex(eparam);
|
re = new Regex(eparam);
|
||||||
|
std::string regex_error;
|
||||||
|
if (!re->ok(®ex_error)) {
|
||||||
|
ms_dbg_a(transaction, 2,
|
||||||
|
"Failed to compile regular expression with macro "
|
||||||
|
+ re->getPattern() + ": " + regex_error);
|
||||||
|
delete re;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
re = m_re;
|
re = m_re;
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,9 @@ int VerifyCC::luhnVerify(const char *ccnumber, int len) {
|
|||||||
bool VerifyCC::init(const std::string ¶m2, std::string *error) {
|
bool VerifyCC::init(const std::string ¶m2, std::string *error) {
|
||||||
m_re.reset(new modsecurity::regex::Regex(m_param));
|
m_re.reset(new modsecurity::regex::Regex(m_param));
|
||||||
|
|
||||||
if (!m_re->ok()) {
|
std::string regex_error;
|
||||||
*error = "Failed to compile regular expression " + m_re->getPattern();
|
if (!m_re->ok(®ex_error)) {
|
||||||
|
*error = "Failed to compile regular expression " + m_re->getPattern() + ": " + regex_error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -28,7 +28,7 @@ class Backend {
|
|||||||
public:
|
public:
|
||||||
virtual ~Backend() {}
|
virtual ~Backend() {}
|
||||||
|
|
||||||
virtual bool ok() const = 0;
|
virtual bool ok(std::string *error = nullptr) const = 0;
|
||||||
|
|
||||||
virtual std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const = 0;
|
virtual std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const = 0;
|
||||||
virtual bool search(const std::string &s, RegexMatch *m = nullptr, ssize_t max_groups = -1) const = 0;
|
virtual bool search(const std::string &s, RegexMatch *m = nullptr, ssize_t max_groups = -1) const = 0;
|
||||||
|
@ -43,10 +43,28 @@ Pcre::Pcre(const std::string& pattern_)
|
|||||||
|
|
||||||
m_pc = pcre_compile(pattern.c_str(), PCRE_DOTALL|PCRE_MULTILINE,
|
m_pc = pcre_compile(pattern.c_str(), PCRE_DOTALL|PCRE_MULTILINE,
|
||||||
&errptr, &erroffset, NULL);
|
&errptr, &erroffset, NULL);
|
||||||
|
if (m_pc == NULL) {
|
||||||
|
m_error = "pcre_compile error at offset " + std::to_string(erroffset) + ": " + std::string(errptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_pce = pcre_study(m_pc, pcre_study_opt, &errptr);
|
m_pce = pcre_study(m_pc, pcre_study_opt, &errptr);
|
||||||
|
if (m_pce == NULL) {
|
||||||
|
m_error = "pcre_study error: " + std::string(errptr);
|
||||||
|
pcre_free(m_pc);
|
||||||
|
m_pc = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pcre_fullinfo(m_pc, m_pce, PCRE_INFO_CAPTURECOUNT, &m_capture_count);
|
int res = pcre_fullinfo(m_pc, m_pce, PCRE_INFO_CAPTURECOUNT, &m_capture_count);
|
||||||
|
if (res != 0) {
|
||||||
|
// N.B. There's no need to free m_pce here, because it's freed in
|
||||||
|
// destructor anyway. However, m_pc must be freed and set to NULL
|
||||||
|
// here so error condition is properly detected by ok() method.
|
||||||
|
m_error = "pcre_fullinfo error: code " + std::to_string(res);
|
||||||
|
pcre_free(m_pc);
|
||||||
|
m_pc = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,8 +43,15 @@ class Pcre : public Backend {
|
|||||||
Pcre(const Pcre&) = delete;
|
Pcre(const Pcre&) = delete;
|
||||||
Pcre& operator=(const Pcre&) = delete;
|
Pcre& operator=(const Pcre&) = delete;
|
||||||
|
|
||||||
virtual bool ok() const override {
|
virtual bool ok(std::string *error = nullptr) const override {
|
||||||
return m_pc != NULL;
|
if (m_pc != NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (error != nullptr) {
|
||||||
|
*error= m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const override;
|
std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const override;
|
||||||
@ -60,6 +67,8 @@ class Pcre : public Backend {
|
|||||||
|
|
||||||
pcre *m_pc = NULL;
|
pcre *m_pc = NULL;
|
||||||
pcre_extra *m_pce = NULL;
|
pcre_extra *m_pce = NULL;
|
||||||
|
|
||||||
|
std::string m_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,8 +40,14 @@ class Re2 : public Backend {
|
|||||||
Re2(const Re2&) = delete;
|
Re2(const Re2&) = delete;
|
||||||
Re2& operator=(const Re2&) = delete;
|
Re2& operator=(const Re2&) = delete;
|
||||||
|
|
||||||
virtual bool ok() const override {
|
virtual bool ok(std::string *error = nullptr) const override {
|
||||||
return re.ok();
|
if (re.ok()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (error != nullptr) {
|
||||||
|
*error = re.error();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const override;
|
std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const override;
|
||||||
|
@ -45,8 +45,8 @@ public:
|
|||||||
: backend(compile_regex_fallback<Args...>(pattern))
|
: backend(compile_regex_fallback<Args...>(pattern))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual bool ok() const override {
|
virtual bool ok(std::string *error = nullptr) const override {
|
||||||
return backend->ok();
|
return backend->ok(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const override {
|
std::vector<RegexMatch> searchAll(const std::string& s, bool overlapping = false) const override {
|
||||||
|
@ -85,5 +85,62 @@
|
|||||||
"SecRuleEngine On",
|
"SecRuleEngine On",
|
||||||
"SecRule REQUEST_HEADERS:Content-Length \"!^0$\" \"id:1,phase:2,pass,t:trim,block\""
|
"SecRule REQUEST_HEADERS:Content-Length \"!^0$\" \"id:1,phase:2,pass,t:trim,block\""
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"version_max":0,
|
||||||
|
"title":"Testing Operator :: @rx with invalid regular expression",
|
||||||
|
"expected":{
|
||||||
|
"parser_error":"Rules error.*Failed to compile regular expression \\(\\(value1\\):"
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRule ARGS \"@rx ((value1)\" \"id:1,phase:2,pass,t:trim\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Testing Operator :: @rx with invalid regular expression after macro expansion",
|
||||||
|
"client":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":123
|
||||||
|
},
|
||||||
|
"server":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":80
|
||||||
|
},
|
||||||
|
"request":{
|
||||||
|
"headers":{
|
||||||
|
"Host":"localhost",
|
||||||
|
"User-Agent":"curl/7.38.0",
|
||||||
|
"Accept":"*/*",
|
||||||
|
"Content-Length": "27",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
},
|
||||||
|
"uri":"/",
|
||||||
|
"method":"POST",
|
||||||
|
"body": [
|
||||||
|
"param1=value1¶m2=value2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"response":{
|
||||||
|
"headers":{
|
||||||
|
"Date":"Mon, 13 Jul 2015 20:02:41 GMT",
|
||||||
|
"Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT",
|
||||||
|
"Content-Type":"text/html"
|
||||||
|
},
|
||||||
|
"body":[
|
||||||
|
"no need."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expected":{
|
||||||
|
"debug_log":"Failed to compile regular expression with macro \\(\\(\\):"
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRule ARGS \"@rx ((%{TX.DOESNT_NEED_TO_EXIST_IT_WILL_BE_AN_EMPTY_STRING})\" \"id:1,phase:2,pass,t:trim\""
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user