mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-11-17 18:05:28 +03:00
Update operator verifyCC to use Regex class
This commit is contained in:
@@ -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 ¶m2, std::string *error) {
|
bool VerifyCC::init(const std::string ¶m2, 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 ¶m, std::string *error) override;
|
bool init(const std::string ¶m, 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
|
||||||
|
|||||||
@@ -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\""
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user