Skip to content

New operator verifySVNR that finds Austrian social security numbers #2063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ script:
#
- make check
- make check-static
- make check-TESTS



2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
v3.0.4 - YYYY-MMM-DD (to be released)
-------------------------------------

- Adds a new operator verifySVNR that checks for Austrian social security numbers
[@Rufus125]
- Allow empty anchored variable
[Issue #2024 - @airween]
- Fixed FILES_NAMES collection after the end of multipart parsing
Expand Down
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ TESTS+=test/test-cases/regression/operator-validate-byte-range.json
TESTS+=test/test-cases/regression/operator-verifycc.json
TESTS+=test/test-cases/regression/operator-verifycpf.json
TESTS+=test/test-cases/regression/operator-verifyssn.json
TESTS+=test/test-cases/regression/operator-verifysvnr.json
TESTS+=test/test-cases/regression/request-body-parser-json.json
TESTS+=test/test-cases/regression/request-body-parser-multipart-crlf.json
TESTS+=test/test-cases/regression/request-body-parser-multipart.json
Expand Down Expand Up @@ -287,6 +288,7 @@ TESTS+=test/test-cases/secrules-language-tests/operators/validateUtf8Encoding.js
TESTS+=test/test-cases/secrules-language-tests/operators/verifyCC.json
TESTS+=test/test-cases/secrules-language-tests/operators/verifycpf.json
TESTS+=test/test-cases/secrules-language-tests/operators/verifyssn.json
TESTS+=test/test-cases/secrules-language-tests/operators/verifysvnr.json
TESTS+=test/test-cases/secrules-language-tests/operators/within.json
TESTS+=test/test-cases/secrules-language-tests/transformations/base64DecodeExt.json
TESTS+=test/test-cases/secrules-language-tests/transformations/base64Decode.json
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ the utilities, follow the commands listed below:
```shell
$ cd /path/to/your/ModSecurity
$ git submodule foreach git pull
$ cd tests
$ cd test
$ ./regression-tests
$ ./unit-tests
```
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ OPERATORS = \
operators/verify_cc.cc \
operators/verify_cpf.cc \
operators/verify_ssn.cc \
operators/verify_svnr.cc \
operators/within.cc \
operators/unconditional_match.cc

Expand Down
2 changes: 2 additions & 0 deletions src/operators/operator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "src/operators/verify_cc.h"
#include "src/operators/verify_cpf.h"
#include "src/operators/verify_ssn.h"
#include "src/operators/verify_svnr.h"
#include "src/operators/within.h"
#include "src/operators/unconditional_match.h"

Expand Down Expand Up @@ -185,6 +186,7 @@ Operator *Operator::instantiate(std::string op, std::string param_str) {
IF_MATCH(verifycc) { return new VerifyCC(std::move(param)); }
IF_MATCH(verifycpf) { return new VerifyCPF(std::move(param)); }
IF_MATCH(verifyssn) { return new VerifySSN(std::move(param)); }
IF_MATCH(verifysvnr) { return new VerifySVNR(std::move(param)); }
IF_MATCH(within) { return new Within(std::move(param)); }

IF_MATCH(unconditionalmatch) {
Expand Down
123 changes: 123 additions & 0 deletions src/operators/verify_svnr.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@

#include "src/operators/verify_svnr.h"

#include <string>

#include "src/operators/operator.h"

#include "modsecurity/rule.h"
#include "modsecurity/rule_message.h"
#include "modsecurity/rules_properties.h"
namespace modsecurity {
namespace operators {

int VerifySVNR::convert_to_int(const char c)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that this function is also used in verify cpf. It seems to me that in a further step, we can move it to utils and make both to share the same base code.

Not need to be done now, that could be an optimization.

{
int n;
if ((c>='0') && (c<='9'))
n = c - '0';
else
n = 0;
return n;
}

bool VerifySVNR::verify(const char *svnrnumber, int len) {
int var_len = len;
int sum = 0;
unsigned int i = 0, svnr_len = 10;
int svnr[11];
char s_svnr[11];
char bad_svnr[12][11] = { "0000000000",
"0123456789",
"1234567890",
"1111111111",
"2222222222",
"3333333333",
"4444444444",
"5555555555",
"6666666666",
"7777777777",
"8888888888",
"9999999999"};

while ((*svnrnumber != '\0') && ( var_len > 0))
{
if (*svnrnumber != '-' || *svnrnumber != '.')
{
if (i < svnr_len && isdigit(*svnrnumber))
{
s_svnr[i] = *svnrnumber;
svnr[i] = convert_to_int(*svnrnumber);
i++;
}
}
svnrnumber++;
var_len--;
}


if (i != svnr_len)
{
return 0;
}
else
{
for (i = 0; i< svnr_len; i++)
{
if (strncmp(s_svnr,bad_svnr[i],svnr_len) == 0)
{
return 0;
}
}
}
//Laufnummer mit 3, 7, 9
//Geburtsdatum mit 5, 8, 4, 2, 1, 6
sum = svnr[0] * 3 + svnr[1] * 7 + svnr[2] * 9 + svnr[4] * 5 + svnr[5] * 8 + svnr[6] * 4 + svnr[7] * 2 + svnr[8] * 1 + svnr[9] * 6;
sum %= 11;
if(sum == 10){
sum = 0;
}
if (sum == svnr[3])
{
return true;
}
return false;
}


bool VerifySVNR::evaluate(Transaction *t, Rule *rule,
const std::string& input, std::shared_ptr<RuleMessage> ruleMessage) {
std::list<SMatch> matches;
bool is_svnr = false;
int i;

if (m_param.empty()) {
return is_svnr;
}

for (i = 0; i < input.size() - 1 && is_svnr == false; i++) {
matches = m_re->searchAll(input.substr(i, input.size()));

for (const auto & i : matches) {
is_svnr = verify(i.str().c_str(), i.str().size());
if (is_svnr) {
logOffset(ruleMessage, i.offset(), i.str().size());
if (rule && t && rule->m_containsCaptureAction) {
t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", i.str());
ms_dbg_a(t, 7, "Added VerifySVNR match TX.0: " + \
i.str());
}

goto out;
}
}
}

out:
return is_svnr;
}


} // namespace operators
} // namespace modsecurity
55 changes: 55 additions & 0 deletions src/operators/verify_svnr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

#ifndef SRC_OPERATORS_VERIFY_SVNR_H_
#define SRC_OPERATORS_VERIFY_SVNR_H_

#include <string>
#include <memory>
#include <utility>

#include "src/operators/operator.h"
#include "src/utils/regex.h"


namespace modsecurity {
using Utils::SMatch;
using Utils::regex_search;
using Utils::Regex;

namespace operators {

class VerifySVNR : public Operator {
public:
/** @ingroup ModSecurity_Operator */
explicit VerifySVNR(std::unique_ptr<RunTimeString> param)
: Operator("VerifySVNR", std::move(param)) {
m_re = new Regex(m_param);
}

~VerifySVNR() {
delete m_re;
}
bool evaluate(Transaction *transaction, Rule *rule,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do not need to specify those here. VerifySVNR inherit from Operator which already contains code to do exactly the same -

https://github.com/SpiderLabs/ModSecurity/blob/6d266fae8549ac425ded31692f6d7766ca0bdc72/src/operators/operator.h#L121

It is safe to remove this evaluate declaration. It is better to remove, so we will have a cleaner code in case of a refactoring or major change.

const std::string &input) override {
return evaluate(transaction, NULL, input, NULL);
}
bool evaluate(Transaction *transaction,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the evaluate above. No need to co-exist here.

const std::string &input) override {
return evaluate(transaction, NULL, input);
}
bool evaluate(Transaction *transaction, Rule *rule,
const std::string& input,
std::shared_ptr<RuleMessage> ruleMessage) override;

int convert_to_int(const char c);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those could be private. Their usage is restricted to the very own class.

bool verify(const char *ssnumber, int len);

private:
Regex *m_re;
};

} // namespace operators
} // namespace modsecurity


#endif // SRC_OPERATORS_VERIFY_SVNR_H_

2 changes: 1 addition & 1 deletion src/parser/seclang-parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6645,7 +6645,7 @@ namespace yy {
"\"OPERATOR_VALIDATE_DTD\"", "\"OPERATOR_VALIDATE_HASH\"",
"\"OPERATOR_VALIDATE_SCHEMA\"", "\"OPERATOR_VALIDATE_URL_ENCODING\"",
"\"OPERATOR_VALIDATE_UTF8_ENCODING\"", "\"OPERATOR_VERIFY_CC\"",
"\"OPERATOR_VERIFY_CPF\"", "\"OPERATOR_VERIFY_SSN\"",
"\"OPERATOR_VERIFY_CPF\"", "\"OPERATOR_VERIFY_SSN\"", "\"OPERATOR_VERIFY_SVNR\"",
"\"OPERATOR_WITHIN\"", "CONFIG_DIR_AUDIT_LOG_FMT", "JSON", "NATIVE",
"\"ACTION_CTL_RULE_ENGINE\"", "\"Accuracy\"", "\"Allow\"", "\"Append\"",
"\"AuditLog\"", "\"Block\"", "\"Capture\"", "\"Chain\"",
Expand Down
20 changes: 17 additions & 3 deletions src/parser/seclang-parser.hh
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class Driver;
#include "src/operators/verify_cc.h"
#include "src/operators/verify_cpf.h"
#include "src/operators/verify_ssn.h"
#include "src/operators/verify_svnr.h"
#include "src/operators/within.h"


Expand Down Expand Up @@ -1355,7 +1356,8 @@ namespace yy {
TOK_RUN_TIME_VAR_TIME_YEAR = 591,
TOK_VARIABLE = 592,
TOK_DICT_ELEMENT = 593,
TOK_DICT_ELEMENT_REGEXP = 594
TOK_DICT_ELEMENT_REGEXP = 594,
TOK_OPERATOR_VERIFY_SVNR = 595
};
};

Expand Down Expand Up @@ -2046,6 +2048,10 @@ namespace yy {
symbol_type
make_OPERATOR_VERIFY_SSN (YY_COPY (location_type) l);

static
symbol_type
make_OPERATOR_VERIFY_SVNR (YY_COPY (location_type) l);

static
symbol_type
make_OPERATOR_WITHIN (YY_COPY (location_type) l);
Expand Down Expand Up @@ -3114,7 +3120,7 @@ namespace yy {
325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
335, 336, 337, 338, 339
};
const unsigned user_token_number_max_ = 594;
const unsigned user_token_number_max_ = 595;
const token_number_type undef_token_ = 2;

if (static_cast<int> (t) <= yyeof_)
Expand Down Expand Up @@ -4027,7 +4033,8 @@ namespace yy {
555, 556, 557, 558, 559, 560, 561, 562, 563, 564,
565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
575, 576, 577, 578, 579, 580, 581, 582, 583, 584,
585, 586, 587, 588, 589, 590, 591, 592, 593, 594
585, 586, 587, 588, 589, 590, 591, 592, 593, 594,
595
};
return static_cast<token_type> (yytoken_number_[type]);
}
Expand Down Expand Up @@ -4992,6 +4999,13 @@ namespace yy {
return symbol_type (token::TOK_OPERATOR_VERIFY_SSN, YY_MOVE (l));
}

inline
seclang_parser::symbol_type
seclang_parser::make_OPERATOR_VERIFY_SVNR (YY_COPY (location_type) l)
{
return symbol_type (token::TOK_OPERATOR_VERIFY_SVNR, YY_MOVE (l));
}

inline
seclang_parser::symbol_type
seclang_parser::make_OPERATOR_WITHIN (YY_COPY (location_type) l)
Expand Down
6 changes: 6 additions & 0 deletions src/parser/seclang-parser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class Driver;
#include "src/operators/verify_cc.h"
#include "src/operators/verify_cpf.h"
#include "src/operators/verify_ssn.h"
#include "src/operators/verify_svnr.h"
#include "src/operators/within.h"


Expand Down Expand Up @@ -466,6 +467,7 @@ using namespace modsecurity::operators;
OPERATOR_VERIFY_CC "OPERATOR_VERIFY_CC"
OPERATOR_VERIFY_CPF "OPERATOR_VERIFY_CPF"
OPERATOR_VERIFY_SSN "OPERATOR_VERIFY_SSN"
OPERATOR_VERIFY_SVNR "OPERATOR_VERIFY_SVNR"
OPERATOR_WITHIN "OPERATOR_WITHIN"

CONFIG_DIR_AUDIT_LOG_FMT
Expand Down Expand Up @@ -960,6 +962,10 @@ op_before_init:
{
OPERATOR_CONTAINER($$, new operators::VerifySSN(std::move($2)));
}
| OPERATOR_VERIFY_SVNR run_time_string
{
OPERATOR_CONTAINER($$, new operators::VerifySVNR(std::move($2)));
}
| OPERATOR_GSB_LOOKUP run_time_string
{
/* $$ = new operators::GsbLookup($1); */
Expand Down
Loading