mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-13 13:26:01 +03:00
Support equals sign in XPath expressions
This commit is contained in:
parent
dabf79eec2
commit
ec1232a69b
2
CHANGES
2
CHANGES
@ -1,6 +1,8 @@
|
|||||||
v3.x.y - YYYY-MMM-DD (to be released)
|
v3.x.y - YYYY-MMM-DD (to be released)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
- Support equals sign in XPath expressions
|
||||||
|
[Issue #2328 - @dennus, @martinhsv]
|
||||||
- Encode two special chars in error.log output
|
- Encode two special chars in error.log output
|
||||||
[Issue #2854 - @airween, @martinhsv]
|
[Issue #2854 - @airween, @martinhsv]
|
||||||
- Add JIT support for PCRE2
|
- Add JIT support for PCRE2
|
||||||
|
@ -279,6 +279,7 @@ TESTS+=test/test-cases/regression/variable-variation-count.json
|
|||||||
TESTS+=test/test-cases/regression/variable-variation-exclusion.json
|
TESTS+=test/test-cases/regression/variable-variation-exclusion.json
|
||||||
TESTS+=test/test-cases/regression/variable-WEBAPPID.json
|
TESTS+=test/test-cases/regression/variable-WEBAPPID.json
|
||||||
TESTS+=test/test-cases/regression/variable-WEBSERVER_ERROR_LOG.json
|
TESTS+=test/test-cases/regression/variable-WEBSERVER_ERROR_LOG.json
|
||||||
|
TESTS+=test/test-cases/regression/variable-XML.json
|
||||||
TESTS+=test/test-cases/secrules-language-tests/operators/beginsWith.json
|
TESTS+=test/test-cases/secrules-language-tests/operators/beginsWith.json
|
||||||
TESTS+=test/test-cases/secrules-language-tests/operators/contains.json
|
TESTS+=test/test-cases/secrules-language-tests/operators/contains.json
|
||||||
TESTS+=test/test-cases/secrules-language-tests/operators/containsWord.json
|
TESTS+=test/test-cases/secrules-language-tests/operators/containsWord.json
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -897,6 +897,7 @@ namespace yy {
|
|||||||
// "RUN_TIME_VAR_TIME_YEAR"
|
// "RUN_TIME_VAR_TIME_YEAR"
|
||||||
// "VARIABLE"
|
// "VARIABLE"
|
||||||
// "Dictionary element"
|
// "Dictionary element"
|
||||||
|
// "Dictionary element, with equals"
|
||||||
// "Dictionary element, selected by regexp"
|
// "Dictionary element, selected by regexp"
|
||||||
char dummy1[sizeof (std::string)];
|
char dummy1[sizeof (std::string)];
|
||||||
|
|
||||||
@ -1314,7 +1315,8 @@ namespace yy {
|
|||||||
TOK_RUN_TIME_VAR_TIME_YEAR = 596, // "RUN_TIME_VAR_TIME_YEAR"
|
TOK_RUN_TIME_VAR_TIME_YEAR = 596, // "RUN_TIME_VAR_TIME_YEAR"
|
||||||
TOK_VARIABLE = 597, // "VARIABLE"
|
TOK_VARIABLE = 597, // "VARIABLE"
|
||||||
TOK_DICT_ELEMENT = 598, // "Dictionary element"
|
TOK_DICT_ELEMENT = 598, // "Dictionary element"
|
||||||
TOK_DICT_ELEMENT_REGEXP = 599 // "Dictionary element, selected by regexp"
|
TOK_DICT_ELEMENT_WITH_EQUALS = 599, // "Dictionary element, with equals"
|
||||||
|
TOK_DICT_ELEMENT_REGEXP = 600 // "Dictionary element, selected by regexp"
|
||||||
};
|
};
|
||||||
/// Backward compatibility alias (Bison 3.6).
|
/// Backward compatibility alias (Bison 3.6).
|
||||||
typedef token_kind_type yytokentype;
|
typedef token_kind_type yytokentype;
|
||||||
@ -1331,7 +1333,7 @@ namespace yy {
|
|||||||
{
|
{
|
||||||
enum symbol_kind_type
|
enum symbol_kind_type
|
||||||
{
|
{
|
||||||
YYNTOKENS = 345, ///< Number of tokens.
|
YYNTOKENS = 346, ///< Number of tokens.
|
||||||
S_YYEMPTY = -2,
|
S_YYEMPTY = -2,
|
||||||
S_YYEOF = 0, // "end of file"
|
S_YYEOF = 0, // "end of file"
|
||||||
S_YYerror = 1, // error
|
S_YYerror = 1, // error
|
||||||
@ -1677,23 +1679,24 @@ namespace yy {
|
|||||||
S_RUN_TIME_VAR_TIME_YEAR = 341, // "RUN_TIME_VAR_TIME_YEAR"
|
S_RUN_TIME_VAR_TIME_YEAR = 341, // "RUN_TIME_VAR_TIME_YEAR"
|
||||||
S_VARIABLE = 342, // "VARIABLE"
|
S_VARIABLE = 342, // "VARIABLE"
|
||||||
S_DICT_ELEMENT = 343, // "Dictionary element"
|
S_DICT_ELEMENT = 343, // "Dictionary element"
|
||||||
S_DICT_ELEMENT_REGEXP = 344, // "Dictionary element, selected by regexp"
|
S_DICT_ELEMENT_WITH_EQUALS = 344, // "Dictionary element, with equals"
|
||||||
S_YYACCEPT = 345, // $accept
|
S_DICT_ELEMENT_REGEXP = 345, // "Dictionary element, selected by regexp"
|
||||||
S_input = 346, // input
|
S_YYACCEPT = 346, // $accept
|
||||||
S_line = 347, // line
|
S_input = 347, // input
|
||||||
S_audit_log = 348, // audit_log
|
S_line = 348, // line
|
||||||
S_actions = 349, // actions
|
S_audit_log = 349, // audit_log
|
||||||
S_actions_may_quoted = 350, // actions_may_quoted
|
S_actions = 350, // actions
|
||||||
S_op = 351, // op
|
S_actions_may_quoted = 351, // actions_may_quoted
|
||||||
S_op_before_init = 352, // op_before_init
|
S_op = 352, // op
|
||||||
S_expression = 353, // expression
|
S_op_before_init = 353, // op_before_init
|
||||||
S_variables = 354, // variables
|
S_expression = 354, // expression
|
||||||
S_variables_pre_process = 355, // variables_pre_process
|
S_variables = 355, // variables
|
||||||
S_variables_may_be_quoted = 356, // variables_may_be_quoted
|
S_variables_pre_process = 356, // variables_pre_process
|
||||||
S_var = 357, // var
|
S_variables_may_be_quoted = 357, // variables_may_be_quoted
|
||||||
S_act = 358, // act
|
S_var = 358, // var
|
||||||
S_setvar_action = 359, // setvar_action
|
S_act = 359, // act
|
||||||
S_run_time_string = 360 // run_time_string
|
S_setvar_action = 360, // setvar_action
|
||||||
|
S_run_time_string = 361 // run_time_string
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1927,6 +1930,7 @@ namespace yy {
|
|||||||
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
||||||
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
||||||
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
||||||
|
case symbol_kind::S_DICT_ELEMENT_WITH_EQUALS: // "Dictionary element, with equals"
|
||||||
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
||||||
value.move< std::string > (std::move (that.value));
|
value.move< std::string > (std::move (that.value));
|
||||||
break;
|
break;
|
||||||
@ -2300,6 +2304,7 @@ switch (yykind)
|
|||||||
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
||||||
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
||||||
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
||||||
|
case symbol_kind::S_DICT_ELEMENT_WITH_EQUALS: // "Dictionary element, with equals"
|
||||||
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
||||||
value.template destroy< std::string > ();
|
value.template destroy< std::string > ();
|
||||||
break;
|
break;
|
||||||
@ -7648,6 +7653,21 @@ switch (yykind)
|
|||||||
return symbol_type (token::TOK_DICT_ELEMENT, v, l);
|
return symbol_type (token::TOK_DICT_ELEMENT, v, l);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if 201103L <= YY_CPLUSPLUS
|
||||||
|
static
|
||||||
|
symbol_type
|
||||||
|
make_DICT_ELEMENT_WITH_EQUALS (std::string v, location_type l)
|
||||||
|
{
|
||||||
|
return symbol_type (token::TOK_DICT_ELEMENT_WITH_EQUALS, std::move (v), std::move (l));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static
|
||||||
|
symbol_type
|
||||||
|
make_DICT_ELEMENT_WITH_EQUALS (const std::string& v, const location_type& l)
|
||||||
|
{
|
||||||
|
return symbol_type (token::TOK_DICT_ELEMENT_WITH_EQUALS, v, l);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if 201103L <= YY_CPLUSPLUS
|
#if 201103L <= YY_CPLUSPLUS
|
||||||
static
|
static
|
||||||
symbol_type
|
symbol_type
|
||||||
@ -7993,7 +8013,7 @@ switch (yykind)
|
|||||||
/// Constants.
|
/// Constants.
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
yylast_ = 3344, ///< Last index in yytable_.
|
yylast_ = 3346, ///< Last index in yytable_.
|
||||||
yynnts_ = 16, ///< Number of nonterminal symbols.
|
yynnts_ = 16, ///< Number of nonterminal symbols.
|
||||||
yyfinal_ = 339 ///< Termination state number.
|
yyfinal_ = 339 ///< Termination state number.
|
||||||
};
|
};
|
||||||
@ -8073,10 +8093,11 @@ switch (yykind)
|
|||||||
305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
|
305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
|
||||||
315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
|
315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
|
||||||
325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
|
325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
|
||||||
335, 336, 337, 338, 339, 340, 341, 342, 343, 344
|
335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
|
||||||
|
345
|
||||||
};
|
};
|
||||||
// Last valid token kind.
|
// Last valid token kind.
|
||||||
const int code_max = 599;
|
const int code_max = 600;
|
||||||
|
|
||||||
if (t <= 0)
|
if (t <= 0)
|
||||||
return symbol_kind::S_YYEOF;
|
return symbol_kind::S_YYEOF;
|
||||||
@ -8292,6 +8313,7 @@ switch (yykind)
|
|||||||
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
||||||
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
||||||
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
||||||
|
case symbol_kind::S_DICT_ELEMENT_WITH_EQUALS: // "Dictionary element, with equals"
|
||||||
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
||||||
value.copy< std::string > (YY_MOVE (that.value));
|
value.copy< std::string > (YY_MOVE (that.value));
|
||||||
break;
|
break;
|
||||||
@ -8551,6 +8573,7 @@ switch (yykind)
|
|||||||
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
case symbol_kind::S_RUN_TIME_VAR_TIME_YEAR: // "RUN_TIME_VAR_TIME_YEAR"
|
||||||
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
case symbol_kind::S_VARIABLE: // "VARIABLE"
|
||||||
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
case symbol_kind::S_DICT_ELEMENT: // "Dictionary element"
|
||||||
|
case symbol_kind::S_DICT_ELEMENT_WITH_EQUALS: // "Dictionary element, with equals"
|
||||||
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
case symbol_kind::S_DICT_ELEMENT_REGEXP: // "Dictionary element, selected by regexp"
|
||||||
value.move< std::string > (YY_MOVE (s.value));
|
value.move< std::string > (YY_MOVE (s.value));
|
||||||
break;
|
break;
|
||||||
@ -8646,7 +8669,7 @@ switch (yykind)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // yy
|
} // yy
|
||||||
#line 8650 "seclang-parser.hh"
|
#line 8673 "seclang-parser.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -680,6 +680,7 @@ using namespace modsecurity::operators;
|
|||||||
RUN_TIME_VAR_TIME_YEAR "RUN_TIME_VAR_TIME_YEAR"
|
RUN_TIME_VAR_TIME_YEAR "RUN_TIME_VAR_TIME_YEAR"
|
||||||
VARIABLE "VARIABLE"
|
VARIABLE "VARIABLE"
|
||||||
DICT_ELEMENT "Dictionary element"
|
DICT_ELEMENT "Dictionary element"
|
||||||
|
DICT_ELEMENT_WITH_EQUALS "Dictionary element, with equals"
|
||||||
DICT_ELEMENT_REGEXP "Dictionary element, selected by regexp"
|
DICT_ELEMENT_REGEXP "Dictionary element, selected by regexp"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -420,6 +420,7 @@ DICT_ELEMENT ([^\"|,\n \t}=]|([^\\]\\\"))+
|
|||||||
DICT_ELEMENT_WITH_PIPE [^ =\t"]+
|
DICT_ELEMENT_WITH_PIPE [^ =\t"]+
|
||||||
DICT_ELEMENT_NO_PIPE [^ =\|\t"]+
|
DICT_ELEMENT_NO_PIPE [^ =\|\t"]+
|
||||||
DICT_ELEMENT_NO_MACRO ([^\"|,%{\n \t}=]|([^\\]\\\"))+
|
DICT_ELEMENT_NO_MACRO ([^\"|,%{\n \t}=]|([^\\]\\\"))+
|
||||||
|
DICT_ELEMENT_WITH_EQUALS ([^\"|,\n \t}]|([^\\]\\\"))+
|
||||||
|
|
||||||
DIRECTIVE (?i:SecRule)
|
DIRECTIVE (?i:SecRule)
|
||||||
DIRECTIVE_SECRULESCRIPT (?i:SecRuleScript)
|
DIRECTIVE_SECRULESCRIPT (?i:SecRuleScript)
|
||||||
@ -1065,7 +1066,7 @@ EQUALS_MINUS (?i:=\-)
|
|||||||
[\/]{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()); }
|
||||||
['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['] { BEGIN_PREVIOUS(); yyless(yyleng - 0); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
|
['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['] { BEGIN_PREVIOUS(); yyless(yyleng - 0); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
|
||||||
['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['][|] { BEGIN_PREVIOUS(); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
|
['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['][|] { BEGIN_PREVIOUS(); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
|
||||||
{DICT_ELEMENT} { BEGIN_PREVIOUS(); return p::make_DICT_ELEMENT(yytext, *driver.loc.back()); }
|
{DICT_ELEMENT_WITH_EQUALS} { BEGIN_PREVIOUS(); return p::make_DICT_ELEMENT(yytext, *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()); }
|
||||||
['][\/]{DICT_ELEMENT_NO_PIPE}[\/]['][,] { BEGIN_PREVIOUS(); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
|
['][\/]{DICT_ELEMENT_NO_PIPE}[\/]['][,] { BEGIN_PREVIOUS(); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
|
||||||
|
46
test/test-cases/regression/variable-XML.json
Normal file
46
test/test-cases/regression/variable-XML.json
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"Testing XPath expression with equals sign",
|
||||||
|
"expected":{
|
||||||
|
"http_code": 403
|
||||||
|
},
|
||||||
|
"client":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":123
|
||||||
|
},
|
||||||
|
"request":{
|
||||||
|
"headers":{
|
||||||
|
"Host":"localhost",
|
||||||
|
"User-Agent":"curl/7.38.0",
|
||||||
|
"Accept":"*/*",
|
||||||
|
"Content-Type": "text/xml"
|
||||||
|
},
|
||||||
|
"uri":"/?key=value&key=other_value",
|
||||||
|
"method":"POST",
|
||||||
|
"body": [
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||||
|
"<!DOCTYPE author [",
|
||||||
|
"<!ELEMENT book ANY>",
|
||||||
|
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||||
|
"]>",
|
||||||
|
"<bookstore>",
|
||||||
|
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||||
|
"</bookstore>"
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
"server":{
|
||||||
|
"ip":"200.249.12.31",
|
||||||
|
"port":80
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecRequestBodyAccess On",
|
||||||
|
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||||
|
"SecRule XML://bookstore/*[local-name()='some-tag'] \"bbb\" \"id:500012,phase:3,t:none,t:lowercase,log,deny,status:403\""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user