This commit is contained in:
Sebastien Blot 2023-10-18 13:42:56 +02:00
parent d3bb9f8ae1
commit 511468b8fe
No known key found for this signature in database
GPG key ID: DFC2902F40449F6A
5 changed files with 60 additions and 9 deletions

View file

@ -149,6 +149,12 @@ func (w *WaapSource) Configure(yamlConfig []byte, logger *log.Entry) error {
return fmt.Errorf("no waap_config provided")
}
err = w.WaapRuntime.ProcessOnLoadRules()
if err != nil {
return fmt.Errorf("unable to process on load rules : %s", err)
}
w.WaapRunners = make([]WaapRunner, w.config.Routines)
for nbRoutine := 0; nbRoutine < w.config.Routines; nbRoutine++ {

View file

@ -186,6 +186,35 @@ func (wc *WaapConfig) Build() (*WaapRuntimeConfig, error) {
return ret, nil
}
func (w *WaapRuntimeConfig) ProcessOnLoadRules() error {
for _, rule := range w.CompiledOnMatch {
if rule.FilterExpr != nil {
output, err := expr.Run(rule.FilterExpr, GetHookEnv(w, ParsedRequest{}))
if err != nil {
return fmt.Errorf("unable to run filter %s : %w", rule.Filter, err)
}
switch t := output.(type) {
case bool:
if !t {
log.Infof("filter didnt match")
continue
}
default:
log.Errorf("Filter must return a boolean, can't filter")
continue
}
}
for _, applyExpr := range rule.ApplyExpr {
_, err := expr.Run(applyExpr, GetHookEnv(w, ParsedRequest{}))
if err != nil {
log.Errorf("unable to apply filter: %s", err)
continue
}
}
}
return nil
}
func (w *WaapRuntimeConfig) ProcessOnMatchRules(request ParsedRequest) error {
for _, rule := range w.CompiledOnMatch {

View file

@ -3,6 +3,7 @@ package waf
import (
"fmt"
"strings"
"time"
)
type VPatchRule struct {
@ -17,8 +18,6 @@ type VPatchRule struct {
Detect string `yaml:"detect"` //@detectXSS, @detectSQLi, etc
Logic string `yaml:"logic,omitempty"` // "AND", "OR", or empty if not applicable
SubRules []VPatchRule `yaml:"sub_rules,omitempty"`
id int
}
func (v *VPatchRule) String() string {
@ -46,26 +45,21 @@ func (v *VPatchRule) constructRule(depth int) string {
switch v.Logic {
case "AND":
// Add "chain" to the current rule
result = strings.TrimSuffix(result, `"`) + `,chain"` + "\n"
for _, subRule := range v.SubRules {
result += subRule.constructRule(depth + 1)
}
case "OR":
skips := countTotalRules(v.SubRules) - 1
// If the "OR" rule is at the top level and is followed by any rule, we need to count that too
if depth == 0 {
skips++ // For the current rule
skips++
}
// Add the skip directive to the current rule too
result = strings.TrimSuffix(result, `"`) + fmt.Sprintf(`,skip:%d"`+"\n", skips)
for _, subRule := range v.SubRules {
skips--
if skips > 0 {
// Append skip directive and decrease the skip count
result += strings.TrimSuffix(subRule.singleRuleString(), `"`) + fmt.Sprintf(`,skip:%d"`+"\n", skips)
} else {
// If no skip is required, append only a newline
result += subRule.singleRuleString() + "\n"
}
}
@ -91,7 +85,9 @@ func (v *VPatchRule) singleRuleString() string {
ruleStr = fmt.Sprintf(`SecRule %s "%s"`, v.Target, operator)
}
actions := fmt.Sprintf(` "id:%d,deny,log`, v.id)
//FIXME: phase2 should probably not be hardcoded
//Find a better way than using time.Now().UnixMilli() to generate a unique ID
actions := fmt.Sprintf(` "id:%d,deny,log,phase:2`, time.Now().UnixNano())
// Handle transformation
if v.Transform != "" {

View file

@ -33,6 +33,25 @@ func TestVPatchRuleString(t *testing.T) {
},
},
expected: `SecRule ARGS:bar "@rx [0-9]" "id:0,deny,log,chain"
SecRule REQUEST_URI "@rx /joomla/index.php/component/users/" "id:0,deny,log"`,
},
{
name: "AND Logic Rule",
rule: VPatchRule{
Logic: "AND",
SubRules: []VPatchRule{
{
Target: "REQUEST_URI",
Match: "/joomla/index.php/component/users/",
},
{
Target: "ARGS",
Variable: "bar",
Match: "[0-9]",
},
},
},
expected: `SecRule ARGS:bar "@rx [0-9]" "id:0,deny,log,chain"
SecRule REQUEST_URI "@rx /joomla/index.php/component/users/" "id:0,deny,log"`,
},
{

View file

@ -27,6 +27,7 @@ type WaapCollectionConfig struct {
SecLangFilesRules []string `yaml:"seclang_files_rules"`
SecLangRules []string `yaml:"seclang_rules"`
Rules []VPatchRule `yaml:"rules"`
Data interface{} `yaml:"data"` //Ignore it
}
func LoadCollection(collection string) (WaapCollection, error) {