Update operator verifyCC to use Regex class

This commit is contained in:
WGH
2019-01-30 14:46:11 +03:00
committed by Felipe Zimmerle
parent 55b81f0e10
commit 9c3c4dc587
3 changed files with 34 additions and 82 deletions

View File

@@ -15,38 +15,15 @@
#include "src/operators/verify_cc.h" #include "src/operators/verify_cc.h"
#include <pcre.h>
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#include "src/operators/operator.h" #include "src/operators/operator.h"
#if PCRE_HAVE_JIT
#define pcre_study_opt PCRE_STUDY_JIT_COMPILE
#else
#define pcre_study_opt 0
#endif
namespace modsecurity { namespace modsecurity {
namespace operators { namespace operators {
VerifyCC::~VerifyCC() {
if (m_pc != NULL) {
pcre_free(m_pc);
m_pc = NULL;
}
if (m_pce != NULL) {
#if PCRE_HAVE_JIT
pcre_free_study(m_pce);
#else
pcre_free(m_pce);
#endif
m_pce = NULL;
}
}
/** /**
* Luhn Mod-10 Method (ISO 2894/ANSI 4.13) * Luhn Mod-10 Method (ISO 2894/ANSI 4.13)
*/ */
@@ -90,72 +67,38 @@ int VerifyCC::luhnVerify(const char *ccnumber, int len) {
bool VerifyCC::init(const std::string &param2, std::string *error) { bool VerifyCC::init(const std::string &param2, std::string *error) {
const char *errptr = NULL; m_re.reset(new modsecurity::regex::Regex(m_param));
int erroffset = 0;
m_pc = pcre_compile(m_param.c_str(), PCRE_DOTALL|PCRE_MULTILINE, if (!m_re->ok()) {
&errptr, &erroffset, NULL); *error = "Failed to compile regular expression " + m_re->getPattern();
if (m_pc == NULL) {
error->assign(errptr);
return false; return false;
} }
m_pce = pcre_study(m_pc, pcre_study_opt, &errptr);
if (m_pce == NULL) {
if (errptr == NULL) {
/*
* Per pcre_study(3) m_pce == NULL && errptr == NULL means
* that no addional information is found, so no need to study
*/
return true;
}
error->assign(errptr);
return false;
}
return true; return true;
} }
bool VerifyCC::evaluate(Transaction *t, Rule *rule, bool VerifyCC::evaluate(Transaction *t, Rule *rule,
const std::string& i, std::shared_ptr<RuleMessage> ruleMessage) { const std::string& i, std::shared_ptr<RuleMessage> ruleMessage) {
int offset = 0;
bool is_cc = false;
int target_length = i.length();
for (offset = 0; offset < target_length; offset++) { // ModSecurity v2 chacked for overlapping matches here,
std::string match; // so do we here
int ovector[33]; for (const auto &m : m_re->searchAll(i, /* overlapping */ true)) {
memset(ovector, 0, sizeof(ovector)); const auto &s = m.group(0).string;
int ret = pcre_exec(m_pc, m_pce, i.c_str(), i.size(), offset, bool is_cc = luhnVerify(s.data(), s.size());
0, ovector, 33) > 0;
/* If there was no match, then we are done. */
if (ret == PCRE_ERROR_NOMATCH) {
break;
}
if (ret < 0) {
return false;
}
if (ret > 0) {
match = std::string(i, ovector[0], ovector[1] - ovector[0]);
is_cc = luhnVerify(match.c_str(), match.size());
if (is_cc) { if (is_cc) {
if (t) { if (t) {
if (rule && t && rule->m_containsCaptureAction) { if (rule && t && rule->m_containsCaptureAction) {
t->m_collections.m_tx_collection->storeOrUpdateFirst( t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", std::string(match)); "0", s);
ms_dbg_a(t, 7, "Added VerifyCC match TX.0: " + \ ms_dbg_a(t, 7, "Added VerifyCC match TX.0: " + s);
std::string(match));
} }
ms_dbg_a(t, 9, "CC# match \"" + m_param + ms_dbg_a(t, 9, "CC# match \"" + m_param +
"\" at " + i + ". [offset " + "\" at " + i + ". [offset " +
std::to_string(offset) + "]"); std::to_string(m.group(0).offset) + "]");
} }
return true; return true;
} }
} }
}
return false; return false;
} }

View File

@@ -16,7 +16,6 @@
#ifndef SRC_OPERATORS_VERIFY_CC_H_ #ifndef SRC_OPERATORS_VERIFY_CC_H_
#define SRC_OPERATORS_VERIFY_CC_H_ #define SRC_OPERATORS_VERIFY_CC_H_
#include <pcre.h>
#include <string> #include <string>
#include <memory> #include <memory>
#include <utility> #include <utility>
@@ -30,10 +29,8 @@ class VerifyCC : public Operator {
public: public:
/** @ingroup ModSecurity_Operator */ /** @ingroup ModSecurity_Operator */
explicit VerifyCC(std::unique_ptr<RunTimeString> param) explicit VerifyCC(std::unique_ptr<RunTimeString> param)
: Operator("VerifyCC", std::move(param)), : Operator("VerifyCC", std::move(param))
m_pc(NULL), { }
m_pce(NULL) { }
~VerifyCC();
int luhnVerify(const char *ccnumber, int len); int luhnVerify(const char *ccnumber, int len);
bool evaluate(Transaction *t, Rule *rule, bool evaluate(Transaction *t, Rule *rule,
@@ -41,8 +38,7 @@ class VerifyCC : public Operator {
std::shared_ptr<RuleMessage> ruleMessage) override; std::shared_ptr<RuleMessage> ruleMessage) override;
bool init(const std::string &param, std::string *error) override; bool init(const std::string &param, std::string *error) override;
private: private:
pcre *m_pc; std::unique_ptr<modsecurity::regex::Regex> m_re;
pcre_extra *m_pce;
}; };
} // namespace operators } // namespace operators

View File

@@ -42,5 +42,18 @@
"SecRuleEngine On", "SecRuleEngine On",
"SecRule ARGS \"@verifycc \\d{13,16}\" \"id:1,phase:2,capture,pass,t:trim\"" "SecRule ARGS \"@verifycc \\d{13,16}\" \"id:1,phase:2,capture,pass,t:trim\""
] ]
},
{
"enabled":1,
"version_min":300000,
"version_max":0,
"title":"Testing Operator :: @verifycc with invalid regular expression",
"expected":{
"parser_error":"Rules error.*Failed to compile regular expression \\\\d\\{13\\,16\\}\\("
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS \"@verifycc \\d{13,16}(\" \"id:1,phase:2,pass,t:trim\""
]
} }
] ]