Adds support to setvar string manipulation

As discussed on #340
This commit is contained in:
Felipe Zimmerle 2020-12-01 21:50:15 -03:00
parent 587cbf3915
commit b8478b11bb
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
10 changed files with 7324 additions and 6903 deletions

View File

@ -1,7 +1,8 @@
v3.x.y - YYYY-MMM-DD (to be released)
-------------------------------------
- EXPERIMENTAL: Adds support to setvar string manipulation
[#340 - @zimmerle, @rcbarnett-zz, @marcstern, @martinhsv]
- Using a custom VariableMatch* implementation
[#2428 - @zimmerle]
- Avoids to cleanup GeoIp on ModSecurity destructor

View File

@ -111,6 +111,7 @@ TESTS+=test/test-cases/regression/action-setenv.json
TESTS+=test/test-cases/regression/action-setrsc.json
TESTS+=test/test-cases/regression/action-setsid.json
TESTS+=test/test-cases/regression/action-setuid.json
TESTS+=test/test-cases/regression/action-setvar.json
TESTS+=test/test-cases/regression/actions.json
TESTS+=test/test-cases/regression/action-skip.json
TESTS+=test/test-cases/regression/action-tag.json

View File

@ -80,6 +80,22 @@ bool SetVar::execute(Transaction *t) const noexcept {
targetValue = resolvedPre;
} else if (m_operation == setToOneOperation) {
targetValue = std::string("1");
} else if (m_operation == appendStringOperation) {
VariableValues l;
std::string value("");
m_variable->evaluate(t, &l);
if (l.size() > 0) {
value = l[0]->getValue();
}
targetValue = resolvedPre + value;
} else if (m_operation == prependStringOperation) {
VariableValues l;
std::string value("");
m_variable->evaluate(t, &l);
if (l.size() > 0) {
value = l[0]->getValue();
}
targetValue = value + resolvedPre;
} else if (m_operation == unsetOperation) {
if (tx) {
tx->del(t, m_variableNameExpanded);

View File

@ -45,6 +45,8 @@ enum SetVarOperation {
setToOneOperation,
/* unset operation */
unsetOperation,
appendStringOperation,
prependStringOperation,
};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -435,6 +435,8 @@ using namespace modsecurity::operators;
SETVAR_OPERATION_EQUALS
SETVAR_OPERATION_EQUALS_PLUS
SETVAR_OPERATION_EQUALS_MINUS
SETVAR_OPERATION_EQUALS_APPEND
SETVAR_OPERATION_EQUALS_PREPEND
NOT "NOT"
OPERATOR_BEGINS_WITH "OPERATOR_BEGINS_WITH"
@ -3024,6 +3026,14 @@ setvar_action:
{
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::substractAndSetOperation, std::move($1), std::move($3)));
}
| var SETVAR_OPERATION_EQUALS_APPEND run_time_string
{
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::appendStringOperation, std::move($1), std::move($3)));
}
| var SETVAR_OPERATION_EQUALS_PREPEND run_time_string
{
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::prependStringOperation, std::move($1), std::move($3)));
}
;
run_time_string:

File diff suppressed because it is too large Load Diff

View File

@ -461,6 +461,8 @@ NEW_LINE [\n\r]+
EQUALS (?i:=)
EQUALS_PLUS (?i:=\+)
EQUALS_MINUS (?i:=\-)
EQUALS_BIGGER (?i:=\>)
EQUALS_LESS (?i:=\<)
%x EXPECTING_ACTION_PREDICATE_VARIABLE
%x TRANSACTION_TO_VARIABLE
@ -696,6 +698,8 @@ EQUALS_MINUS (?i:=\-)
<SETVAR_ACTION_NONQUOTED_WAITING_OPERATION,SETVAR_ACTION_QUOTED_WAITING_OPERATION>{
{EQUALS_PLUS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_PLUS(*driver.loc.back()); }
{EQUALS_MINUS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_MINUS(*driver.loc.back()); }
{EQUALS_BIGGER} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_APPEND(*driver.loc.back()); }
{EQUALS_LESS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_PREPEND(*driver.loc.back()); }
{EQUALS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS(*driver.loc.back()); }
}
@ -1042,6 +1046,8 @@ EQUALS_MINUS (?i:=\-)
<EXPECTING_VAR_PARAMETER_OR_MACRO_QUOTED,EXPECTING_VAR_PARAMETER_OR_MACRO_NONQUOTED>{
{EQUALS_PLUS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_PLUS(*driver.loc.back()); }
{EQUALS_MINUS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_MINUS(*driver.loc.back()); }
{EQUALS_BIGGER} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_APPEND(*driver.loc.back()); }
{EQUALS_LESS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS_PREPEND(*driver.loc.back()); }
{EQUALS} { BEGIN_ACTION_WAITING_CONTENT(); return p::make_SETVAR_OPERATION_EQUALS(*driver.loc.back()); }
[\/]{DICT_ELEMENT_NO_PIPE}[\/][ ] { BEGIN_PREVIOUS(); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 1, yyleng-2), *driver.loc.back()); }
[\/]{DICT_ELEMENT_NO_PIPE}[\/][|] { BEGIN_PREVIOUS(); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 1, yyleng-2), *driver.loc.back()); }

View File

@ -0,0 +1,278 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 1/n",
"expected":{
"debug_log": " Saving variable: SESSION:test with value: PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120curl/7.38.0",
"error_log": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120curl/7.38.0",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS:User-Agent \"^(.*)$\" \"id:'1',phase:2,setvar:SESSION.test=>%{MATCHED_VAR}\"",
"SecRule REQUEST_HEADERS:Cookie \"^(.*)$\" \"id:'2',phase:2,setvar:SESSION.test=>%{MATCHED_VAR}\"",
"SecRule SESSION:test \"PHP\" \"id:'3',phase:2,deny,chain\"",
"SecRule SESSION:test \"curl\" \"\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 2/n",
"expected":{
"debug_log": " Saving variable: SESSION:test with value: curl/7.38.0PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"error_log": "curl/7.38.0PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS:User-Agent \"^(.*)$\" \"id:'1',phase:2,setvar:SESSION.test=>%{MATCHED_VAR}\"",
"SecRule REQUEST_HEADERS:Cookie \"^(.*)$\" \"id:'2',phase:2,setvar:SESSION.test=<%{MATCHED_VAR}\"",
"SecRule SESSION:test \"PHP\" \"id:'3',phase:2,deny,chain\"",
"SecRule SESSION:test \"curl\" \"\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 3/n",
"expected":{
"debug_log": "Saving variable: SESSION:test with value: PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120curl/7.38.0localhost",
"error_log": "\\*\/\\*PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120curl/7.38.0localhost",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS \"^(.*)$\" \"id:'1',phase:2,setvar:SESSION.test=>%{MATCHED_VAR}\"",
"SecRule SESSION:test \"PHP\" \"id:'2',phase:2,deny,chain\"",
"SecRule SESSION:test \"curl\" \"\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 4/n",
"expected":{
"debug_log": "SESSION:test with value: localhostcurl/7.38.0PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"error_log": "localhostcurl/7.38.0PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120\\*\/\\*",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS \"^(.*)$\" \"id:'1',phase:2,setvar:SESSION.test=<%{MATCHED_VAR}\"",
"SecRule SESSION:test \"PHP\" \"id:'2',phase:2,deny,chain\"",
"SecRule SESSION:test \"curl\" \"\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 5/n",
"expected":{
"debug_log": "TX:test with value: localhostcurl/7.38.0PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"error_log": "localhostcurl/7.38.0PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120\\*\/\\*",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS \"^(.*)$\" \"id:'1',phase:2,setvar:TX.test=<%{MATCHED_VAR}\"",
"SecRule TX:test \"PHP\" \"id:'2',phase:2,deny,chain\"",
"SecRule TX:test \"curl\" \"\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 6/n",
"expected":{
"debug_log": "Saving variable: TX:test with value: '-REQUEST_HEADERS:Host: localhost''-REQUEST_HEADERS:User-Agent: curl/7.38.0''-REQUEST_HEADERS:Cookie: PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120''-REQUEST_HEADERS:Accept: \\*\/\\*'",
"error_log": "-REQUEST_HEADERS:Host: localhost''-REQUEST_HEADERS:User-Agent: curl/7.38.0''-REQUEST_HEADERS:Cookie",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS \"^(.*)$\" \"id:'1',phase:2,setvar:TX.test=<'-%{MATCHED_VAR_NAME}: %{MATCHED_VAR}'\"",
"SecRule TX:test \"PHP\" \"id:'2',phase:2,deny,chain\"",
"SecRule TX:test \"curl\" \"\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 7/n",
"expected":{
"debug_log": "Saving variable: TX:test with value: '-REQUEST_HEADERS:Host: localhost /\\?key=value&key=other_value'",
"error_log": "-REQUEST_HEADERS:Host: localhost /\\?key=value&key=other_value''-REQUEST_HEADERS:User-Agent: curl/7.3",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS \"^(.*)$\" \"id:'1',phase:2,setvar:TX.test=<'-%{MATCHED_VAR_NAME}: %{MATCHED_VAR} %{REQUEST_URI}'\"",
"SecRule TX:test \"PHP\" \"id:'2',phase:2,deny,chain\"",
"SecRule TX:test \"curl\" \"\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing setvar action (string) 8/n",
"expected":{
"debug_log": "Saving variable: TX:test2 with value: 'This is test2'': '-REQUEST_HEADERS:Host: localhost",
"error_log": "'This is test2'': '-REQUEST_HEADERS:Host:",
"http_code":403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
},
"uri":"/?key=value&key=other_value",
"method":"GET"
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_HEADERS \"^(.*)$\" \"id:'1',phase:2,setvar:TX.test=<'-%{MATCHED_VAR_NAME}: %{MATCHED_VAR} %{REQUEST_URI}'\"",
"SecRule REQUEST_HEADERS:Host \"^(.*)$\" \"id:'2',phase:2,setvar:TX.test2='This is test2'\"",
"SecRule REQUEST_HEADERS:Host \"^(.*)$\" \"id:'3',phase:2,setvar:TX.test2=<': %{TX.test}'\"",
"SecRule TX:test2 \"PHP\" \"id:'4',phase:2,deny,chain\"",
"SecRule TX:test2 \"curl\" \"\""
]
}
]