From 2dbeb395a91b8e36481e9f7a29c0aecbd31480f5 Mon Sep 17 00:00:00 2001 From: Juan Pablo Tosso Date: Tue, 24 Aug 2021 22:55:20 -0400 Subject: [PATCH] now you can disable operators, actions and directives --- seclang/parser.go | 48 ++++++++++++++++++++++++------------------ seclang/rule_parser.go | 10 ++++++++- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/seclang/parser.go b/seclang/parser.go index a77a3f158..27f177afb 100644 --- a/seclang/parser.go +++ b/seclang/parser.go @@ -29,12 +29,14 @@ import ( // Parser provides functions to evaluate (compile) SecLang directives type Parser struct { - configfile string - configdir string - nextChain bool - RuleEngine string - Waf *engine.Waf - lastRule *engine.Rule + configfile string + configdir string + nextChain bool + Waf *engine.Waf + DisabledDirectives []string + DisabledRuleActions []string + DisabledRuleOperators []string + lastRule *engine.Rule defaultActions []string currentLine int @@ -115,6 +117,10 @@ func (p *Parser) evaluate(data string) error { opts = strings.Trim(opts, `"`) } + if utils.StringInSlice(directive, p.DisabledDirectives) { + return fmt.Errorf("%s directive is disabled", directive) + } + directives := map[string]Directive{ "SecWebAppId": directiveSecWebAppId, "SecUploadKeepFiles": directiveSecUploadKeepFiles, @@ -171,18 +177,14 @@ func (p *Parser) evaluate(data string) error { "SecDebugLogLevel": directiveSecDebugLogLevel, //Unsupported Directives - "SecAuditLogType": directiveUnsupported, - "SecArgumentSeparator": directiveUnsupported, - "SecCookieFormat": directiveUnsupported, - "SecStatusEngine": directiveUnsupported, - "SecXmlExternalEntity": directiveUnsupported, - "SecStreamOutBodyInspection": directiveUnsupported, - "SecRuleUpdateTargetByTag": directiveUnsupported, - "SecRuleUpdateTargetByMsg": directiveUnsupported, - "SecRuleUpdateTargetById": directiveUnsupported, - "SecRuleUpdateActionById": directiveUnsupported, - "SecRuleScript": directiveUnsupported, - "SecRulePerfTime": directiveUnsupported, + "SecArgumentSeparator": directiveUnsupported, + "SecCookieFormat": directiveUnsupported, + "SecRuleUpdateTargetByTag": directiveUnsupported, + "SecRuleUpdateTargetByMsg": directiveUnsupported, + "SecRuleUpdateTargetById": directiveUnsupported, + "SecRuleUpdateActionById": directiveUnsupported, + "SecRuleScript": directiveUnsupported, + "SecRulePerfTime": directiveUnsupported, } d := directives[directive] if d == nil { @@ -195,7 +197,7 @@ func (p *Parser) evaluate(data string) error { // Rules without operator will become SecActions func (p *Parser) ParseRule(data string, withOperator bool) (*engine.Rule, error) { var err error - rp := NewRuleParser() + rp := NewRuleParser(p) rp.Configdir = p.configdir for _, da := range p.defaultActions { @@ -213,6 +215,9 @@ func (p *Parser) ParseRule(data string, withOperator bool) (*engine.Rule, error) r := regexp.MustCompile(`"(?:[^"\\]|\\.)*"`) matches := r.FindAllString(data, -1) operator := utils.RemoveQuotes(matches[0]) + if utils.StringInSlice(operator, p.DisabledRuleOperators) { + return nil, fmt.Errorf("%s rule operator is disabled", operator) + } err = rp.ParseVariables(vars) if err != nil { return nil, err @@ -291,8 +296,9 @@ func NewParser(waf *engine.Waf) (*Parser, error) { return nil, errors.New("must use a valid waf instance") } p := &Parser{ - Waf: waf, - defaultActions: []string{}, + Waf: waf, + defaultActions: []string{}, + DisabledDirectives: []string{}, } return p, nil } diff --git a/seclang/rule_parser.go b/seclang/rule_parser.go index 4dea66e48..33932de84 100644 --- a/seclang/rule_parser.go +++ b/seclang/rule_parser.go @@ -36,6 +36,7 @@ type ruleAction struct { } type RuleParser struct { + parser *Parser rule *engine.Rule Configdir string defaultActions map[int][]ruleAction @@ -233,6 +234,12 @@ func (p *RuleParser) ParseActions(actions string) error { if err != nil { return err } + //check if forbidden action: + for _, a := range act { + if utils.StringInSlice(a.Key, p.parser.DisabledRuleActions) { + return fmt.Errorf("%s rule action is disabled", a.Key) + } + } //first we execute metadata rules for _, a := range act { if a.Atype == engine.ACTION_TYPE_METADATA { @@ -267,10 +274,11 @@ func (p *RuleParser) Rule() *engine.Rule { // NewRuleParser Creates a new rule parser, each rule parser // will contain a single rule that can be obtained using ruleparser.Rule() -func NewRuleParser() *RuleParser { +func NewRuleParser(p *Parser) *RuleParser { rp := &RuleParser{ rule: engine.NewRule(), defaultActions: map[int][]ruleAction{}, + parser: p, } return rp }