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
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
1 change: 1 addition & 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
114 changes: 114 additions & 0 deletions src/operators/verify_svnr.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@

#include "src/operators/verify_svnr.h"

#include <string>

#include "src/operators/operator.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 if ((c>='A') && (c<='F'))
n = c - 'A' + 10;
else if ((c>='a') && (c<='f'))
n = c - 'a' + 10;
else
n = 0;
return n;
}

bool VerifySVNR::verify(const char *svnrnumber, int len) {
int factor, part_1, part_2, var_len = len;
unsigned int sum = 0, i = 0, svnr_len = 11, c;
int svnr[11];
char s_svnr[11];
char bad_svnr[12][12] = { "00000000000",
"01234567890",
"11111111111",
"22222222222",
"33333333333",
"44444444444",
"55555555555",
"66666666666",
"77777777777",
"88888888888",
"99999999999"};

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 == svnr[3])
{
return true;
}

return false;
}


bool VerifySVNR::evaluate(Transaction *transaction, 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; i++) {
printf ("Decimal i: %d\n", i);
Copy link
Contributor

Choose a reason for hiding this comment

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

Although that is a very useful debug information, it may not a good idea for production I would consider removing it.

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());
break;
}
}
}
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_

46 changes: 46 additions & 0 deletions test/test-cases/regression/operator-verifysvnr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[
Copy link
Contributor

Choose a reason for hiding this comment

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

Thumbs up for the test case :) that really speed up my review. Thank you.

{
"enabled":1,
"version_min":300000,
"title":"Testing Operator :: @verifysvnr (1/2)",
Copy link
Contributor

Choose a reason for hiding this comment

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

This would be 1 of 1.

"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=1237 010180&param2=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":"Added VerifySVNR match TX.0: 1237 010180"
},
"rules":[
"SecRuleEngine On",
"SecRule ARGS \"@verifysvnr ^([0-9]{4} ?[0-9]{8}$\" \"id:1,phase:2,capture,pass,t:trim\""
]
}
]