Skip to content

Commit 0be821d

Browse files
asterite3Felipe Zimmerle
authored andcommitted
change parsing of SetVar actions
Change tokenization of SetVar expressions and use syntax analyzer (seclang-parser) to process them. More precisely: 1 SetVar expression is tokenized in two modes, quoted and not quoted, depending on whether it started with single quote (') 2 Variable name and value can consist of multiple tokens, which are assembled back in syntax analyzer. This allows to support escapes (escape single/double quote, spaces etc.) and correctly detect where the expression ends. Fixes #1529
1 parent e0ebf28 commit 0be821d

File tree

2 files changed

+113
-69
lines changed

2 files changed

+113
-69
lines changed

src/parser/seclang-parser.yy

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -649,13 +649,19 @@ using modsecurity::operators::Operator;
649649
RUN_TIME_VAR_TIME_SEC "RUN_TIME_VAR_TIME_SEC"
650650
RUN_TIME_VAR_TIME_WDAY "RUN_TIME_VAR_TIME_WDAY"
651651
RUN_TIME_VAR_TIME_YEAR "RUN_TIME_VAR_TIME_YEAR"
652+
SETVAR_VARIABLE_PART "SETVAR_VARIABLE_PART"
653+
SETVAR_CONTENT_PART "SETVAR_CONTENT_PART"
652654
VARIABLE "VARIABLE"
653655
DICT_ELEMENT "Dictionary element"
654656
DICT_ELEMENT_REGEXP "Dictionary element, selected by regexp"
655657
;
656658

657659
%type <std::unique_ptr<actions::Action>> act
658660

661+
%type <std::unique_ptr<actions::Action>> setvar_action
662+
%type <std::string> setvar_variable
663+
%type <std::string> setvar_content
664+
659665
%type <std::unique_ptr<std::vector<std::unique_ptr<actions::Action> > > >
660666
actions_may_quoted
661667
actions
@@ -2321,25 +2327,9 @@ act:
23212327
{
23222328
ACTION_CONTAINER($$, new actions::SetUID($1));
23232329
}
2324-
| ACTION_SETVAR NOT VARIABLE
2325-
{
2326-
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::unsetOperation, $3));
2327-
}
2328-
| ACTION_SETVAR VARIABLE
2329-
{
2330-
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::setToOneOperation, $2));
2331-
}
2332-
| ACTION_SETVAR VARIABLE SETVAR_OPERATION_EQUALS FREE_TEXT
2333-
{
2334-
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::setOperation, $2, $4));
2335-
}
2336-
| ACTION_SETVAR VARIABLE SETVAR_OPERATION_EQUALS_PLUS FREE_TEXT
2337-
{
2338-
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::sumAndSetOperation, $2, $4));
2339-
}
2340-
| ACTION_SETVAR VARIABLE SETVAR_OPERATION_EQUALS_MINUS FREE_TEXT
2330+
| ACTION_SETVAR setvar_action
23412331
{
2342-
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::substractAndSetOperation, $2, $4));
2332+
$$ = std::move($2);
23432333
}
23442334
| ACTION_SEVERITY
23452335
{
@@ -2487,6 +2477,53 @@ act:
24872477
}
24882478
;
24892479

2480+
setvar_action:
2481+
NOT setvar_variable
2482+
{
2483+
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::unsetOperation, $2));
2484+
}
2485+
| setvar_variable
2486+
{
2487+
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::setToOneOperation, $1));
2488+
}
2489+
| setvar_variable SETVAR_OPERATION_EQUALS setvar_content
2490+
{
2491+
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::setOperation, $1, $3));
2492+
}
2493+
| setvar_variable SETVAR_OPERATION_EQUALS_PLUS setvar_content
2494+
{
2495+
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::sumAndSetOperation, $1, $3));
2496+
}
2497+
| setvar_variable SETVAR_OPERATION_EQUALS_MINUS setvar_content
2498+
{
2499+
ACTION_CONTAINER($$, new actions::SetVar(actions::SetVarOperation::substractAndSetOperation, $1, $3));
2500+
}
2501+
;
2502+
2503+
setvar_variable:
2504+
SETVAR_VARIABLE_PART
2505+
{
2506+
$$ = $1;
2507+
}
2508+
|
2509+
SETVAR_VARIABLE_PART setvar_variable
2510+
{
2511+
$$ = $1 + $2;
2512+
}
2513+
;
2514+
2515+
setvar_content:
2516+
SETVAR_CONTENT_PART
2517+
{
2518+
$$ = $1;
2519+
}
2520+
|
2521+
SETVAR_CONTENT_PART setvar_content
2522+
{
2523+
$$ = $1 + $2;
2524+
}
2525+
;
2526+
24902527
%%
24912528

24922529
void yy::seclang_parser::error (const location_type& l, const std::string& m) {

src/parser/seclang-scanner.ll

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@ DICT_ELEMENT ([^\"|,\n \t]|([^\\]\\\"))+
328328
DICT_ELEMENT_WITH_PIPE [^ \t"]+
329329

330330

331-
DICT_ELEMENT_TWO [^\"\=]+
331+
DICT_ELEMENT_TWO [^\"\=, \t\r\n\\]*
332+
DICT_ELEMENT_TWO_QUOTED [^\"\'\=\r\n\\]*
332333
DICT_ELEMENT_TWO2 [A-Za-z_ -\%\{\.\}\-\/]+
333334
DIRECTIVE (?i:SecRule)
334335
DIRECTIVE_SECRULESCRIPT (?i:SecRuleScript)
@@ -370,9 +371,14 @@ EQUALS_MINUS (?i:=\-)
370371
%x FINISH_ACTIONS
371372
%x LEXING_ERROR
372373
%x LEXING_ERROR_ACTION
373-
%x SETVAR_ACTION_WAITING_VARIABLE
374-
%x SETVAR_ACTION_WAITING_OPERATION
375-
%x SETVAR_ACTION_WAITING_CONTENT
374+
%x SETVAR_ACTION_NONQUOTED
375+
%x SETVAR_ACTION_NONQUOTED_WAITING_COLLECTION_ELEM
376+
%x SETVAR_ACTION_NONQUOTED_WAITING_OPERATION
377+
%x SETVAR_ACTION_NONQUOTED_WAITING_CONTENT
378+
%x SETVAR_ACTION_QUOTED
379+
%x SETVAR_ACTION_QUOTED_WAITING_COLLECTION_ELEM
380+
%x SETVAR_ACTION_QUOTED_WAITING_OPERATION
381+
%x SETVAR_ACTION_QUOTED_WAITING_CONTENT
376382
377383
%{
378384
// Code run each time a pattern is matched.
@@ -452,7 +458,8 @@ EQUALS_MINUS (?i:=\-)
452458
{ACTION_SETUID}:'{VAR_FREE_TEXT_QUOTE}' { return p::make_ACTION_SETUID(yytext, *driver.loc.back()); }
453459
{ACTION_SETUID}:{VAR_FREE_TEXT_SPACE_COMMA} { return p::make_ACTION_SETUID(yytext, *driver.loc.back()); }
454460
455-
{ACTION_SETVAR}: { BEGIN(SETVAR_ACTION_WAITING_VARIABLE); return p::make_ACTION_SETVAR(*driver.loc.back()); }
461+
{ACTION_SETVAR}:' { BEGIN(SETVAR_ACTION_QUOTED); return p::make_ACTION_SETVAR(*driver.loc.back()); }
462+
{ACTION_SETVAR}: { BEGIN(SETVAR_ACTION_NONQUOTED); return p::make_ACTION_SETVAR(*driver.loc.back()); }
456463
457464
458465
{ACTION_SEVERITY}:'{ACTION_SEVERITY_VALUE}' { return p::make_ACTION_SEVERITY(yytext, *driver.loc.back()); }
@@ -513,61 +520,61 @@ EQUALS_MINUS (?i:=\-)
513520
. { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
514521
}
515522
516-
<SETVAR_ACTION_WAITING_VARIABLE>{
517-
\'* { }
518-
\"* { }
519-
{NOT} { return p::make_NOT(*driver.loc.back()); }
520-
{VARIABLE_TX}(\:[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
521-
{VARIABLE_TX}(\:{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
522-
{VARIABLE_TX}(\.[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
523-
{VARIABLE_TX}(\.{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
524-
{VARIABLE_SESSION}(\:[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
525-
{VARIABLE_SESSION}(\:{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
526-
{VARIABLE_SESSION}(\.[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
527-
{VARIABLE_SESSION}(\.{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
528-
{VARIABLE_RESOURCE}(\:[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
529-
{VARIABLE_RESOURCE}(\:{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
530-
{VARIABLE_RESOURCE}(\.[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
531-
{VARIABLE_RESOURCE}(\.{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
532-
{VARIABLE_IP}(\:[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
533-
{VARIABLE_IP}(\:{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
534-
{VARIABLE_IP}(\.[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
535-
{VARIABLE_IP}(\.{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
536-
{VARIABLE_USER}(\:[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
537-
{VARIABLE_USER}(\:{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
538-
{VARIABLE_USER}(\.[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
539-
{VARIABLE_USER}(\.{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
540-
{VARIABLE_GLOBAL}(\:[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
541-
{VARIABLE_GLOBAL}(\:{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
542-
{VARIABLE_GLOBAL}(\.[\']{DICT_ELEMENT_TWO}[\'])? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
543-
{VARIABLE_GLOBAL}(\.{DICT_ELEMENT_TWO})? { BEGIN(SETVAR_ACTION_WAITING_OPERATION); return p::make_VARIABLE(yytext, *driver.loc.back()); }
544-
. { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
545-
[ \t]*\\\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); }
546-
[ \t]*\\\r\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); }
523+
<SETVAR_ACTION_NONQUOTED>{
524+
{NOT} { return p::make_NOT(*driver.loc.back()); }
525+
{VARIABLE_TX}|{VARIABLE_SESSION}|{VARIABLE_RESOURCE}|{VARIABLE_IP}|{VARIABLE_USER}|{VARIABLE_GLOBAL}[:\.] { BEGIN(SETVAR_ACTION_NONQUOTED_WAITING_COLLECTION_ELEM); return p::make_SETVAR_VARIABLE_PART(yytext, *driver.loc.back());}
526+
{VARIABLE_TX}|{VARIABLE_SESSION}|{VARIABLE_RESOURCE}|{VARIABLE_IP}|{VARIABLE_USER}|{VARIABLE_GLOBAL} { BEGIN(SETVAR_ACTION_NONQUOTED_WAITING_OPERATION); return p::make_SETVAR_VARIABLE_PART(yytext, *driver.loc.back());}
527+
.|\n { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
547528
}
548529
530+
<SETVAR_ACTION_NONQUOTED_WAITING_COLLECTION_ELEM>{
531+
{DICT_ELEMENT_TWO} { return p::make_SETVAR_VARIABLE_PART(yytext, *driver.loc.back()); }
532+
\\(.|\n) { return p::make_SETVAR_VARIABLE_PART(yytext + 1, *driver.loc.back()); }
533+
.|\n { BEGIN(SETVAR_ACTION_NONQUOTED_WAITING_OPERATION); yyless(0); }
534+
}
535+
536+
<SETVAR_ACTION_NONQUOTED_WAITING_OPERATION>{
537+
{EQUALS_PLUS} { BEGIN(SETVAR_ACTION_NONQUOTED_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS_PLUS(*driver.loc.back()); }
538+
{EQUALS_MINUS} { BEGIN(SETVAR_ACTION_NONQUOTED_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS_MINUS(*driver.loc.back()); }
539+
{EQUALS} { BEGIN(SETVAR_ACTION_NONQUOTED_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS(*driver.loc.back()); }
540+
.|\n { BEGIN(EXPECTING_ACTIONS); yyless(0);}
541+
}
542+
543+
<SETVAR_ACTION_NONQUOTED_WAITING_CONTENT>{
544+
\\(.|\n) { return p::make_SETVAR_CONTENT_PART(yytext + 1, *driver.loc.back()); }
545+
[^,"\n\r\t \\]+ { return p::make_SETVAR_CONTENT_PART(yytext, *driver.loc.back()); }
546+
.|\n { BEGIN(EXPECTING_ACTIONS); yyless(0); }
547+
}
549548

549+
<SETVAR_ACTION_QUOTED>{
550+
{NOT} { return p::make_NOT(*driver.loc.back()); }
551+
{VARIABLE_TX}|{VARIABLE_SESSION}|{VARIABLE_RESOURCE}|{VARIABLE_IP}|{VARIABLE_USER}|{VARIABLE_GLOBAL}[:\.] { BEGIN(SETVAR_ACTION_QUOTED_WAITING_COLLECTION_ELEM); return p::make_SETVAR_VARIABLE_PART(yytext, *driver.loc.back());}
552+
{VARIABLE_TX}|{VARIABLE_SESSION}|{VARIABLE_RESOURCE}|{VARIABLE_IP}|{VARIABLE_USER}|{VARIABLE_GLOBAL} { BEGIN(SETVAR_ACTION_QUOTED_WAITING_OPERATION); return p::make_SETVAR_VARIABLE_PART(yytext, *driver.loc.back());}
553+
.|\n { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
554+
}
550555

556+
<SETVAR_ACTION_QUOTED_WAITING_COLLECTION_ELEM>{
557+
{DICT_ELEMENT_TWO_QUOTED} { return p::make_SETVAR_VARIABLE_PART(yytext, *driver.loc.back()); }
558+
\\(.|\n) { return p::make_SETVAR_VARIABLE_PART(yytext + 1, *driver.loc.back()); }
559+
.|\n { BEGIN(SETVAR_ACTION_QUOTED_WAITING_OPERATION); yyless(0); }
560+
}
551561

552-
<SETVAR_ACTION_WAITING_OPERATION>{
553-
[ \t]*\n { BEGIN(INITIAL); yyless(1); }
554-
[ \t]*\r\n { BEGIN(INITIAL); driver.loc.back()->lines(1); driver.loc.back()->step(); }
555-
[ \t]*\n { BEGIN(EXPECTING_ACTIONS); yyless(yyleng); driver.loc.back()->lines(1); driver.loc.back()->step(); }
556-
[ \t]*\r\n { BEGIN(EXPECTING_ACTIONS); yyless(yyleng); driver.loc.back()->lines(1); driver.loc.back()->step(); }
557-
[ \t]*\"[ \t]* { }
558-
[ \t]*\'[ \t]* { }
559-
\"[ \t]*\n { BEGIN(EXPECTING_ACTIONS); yyless(1); }
560-
\"[ \t]*\r\n { BEGIN(EXPECTING_ACTIONS); driver.loc.back()->lines(1); driver.loc.back()->step(); }
561-
{EQUALS_PLUS} { BEGIN(SETVAR_ACTION_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS_PLUS(*driver.loc.back()); }
562-
{EQUALS_MINUS} { BEGIN(SETVAR_ACTION_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS_MINUS(*driver.loc.back()); }
563-
{EQUALS} { BEGIN(SETVAR_ACTION_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS(*driver.loc.back()); }
564-
. { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
562+
<SETVAR_ACTION_QUOTED_WAITING_OPERATION>{
563+
{EQUALS_PLUS} { BEGIN(SETVAR_ACTION_QUOTED_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS_PLUS(*driver.loc.back()); }
564+
{EQUALS_MINUS} { BEGIN(SETVAR_ACTION_QUOTED_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS_MINUS(*driver.loc.back()); }
565+
{EQUALS} { BEGIN(SETVAR_ACTION_QUOTED_WAITING_CONTENT); return p::make_SETVAR_OPERATION_EQUALS(*driver.loc.back()); }
566+
\' { BEGIN(EXPECTING_ACTIONS); }
567+
.|\n { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
565568
}
566569
567-
<SETVAR_ACTION_WAITING_CONTENT>{
568-
[^,"\n]+ { BEGIN(EXPECTING_ACTIONS); return p::make_FREE_TEXT(yytext, *driver.loc.back()); }
570+
<SETVAR_ACTION_QUOTED_WAITING_CONTENT>{
571+
\\(.|\n) { return p::make_SETVAR_CONTENT_PART(yytext + 1, *driver.loc.back()); }
572+
[^"\'\n\r\\]* { return p::make_SETVAR_CONTENT_PART(yytext, *driver.loc.back()); }
573+
\' { BEGIN(EXPECTING_ACTIONS); }
574+
.|\n { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
569575
}
570576
577+
571578
<FINISH_ACTIONS>{
572579
<<EOF>> { BEGIN(INITIAL); yyless(0); p::make_NEW_LINE(*driver.loc.back()); }
573580
. { BEGIN(INITIAL); }

0 commit comments

Comments
 (0)