diff --git a/go.mod b/go.mod index 7db22663f..2d208484a 100644 --- a/go.mod +++ b/go.mod @@ -79,9 +79,9 @@ require ( github.com/umahmood/haversine v0.0.0-20151105152445-808ab04add26 github.com/wasilibs/go-re2 v1.3.0 github.com/xhit/go-simple-mail/v2 v2.16.0 - golang.org/x/crypto v0.15.0 + golang.org/x/crypto v0.16.0 golang.org/x/mod v0.11.0 - golang.org/x/sys v0.14.0 + golang.org/x/sys v0.15.0 google.golang.org/grpc v1.56.3 google.golang.org/protobuf v1.31.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 @@ -90,7 +90,7 @@ require ( ) require ( - github.com/crowdsecurity/coraza/v3 v3.0.0-20231114091225-b0f8bc435a75 + github.com/crowdsecurity/coraza/v3 v3.0.0-20231204125126-35deffad7734 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.0 @@ -200,9 +200,9 @@ require ( github.com/zclconf/go-cty v1.8.0 // indirect go.mongodb.org/mongo-driver v1.9.4 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/net v0.18.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/term v0.14.0 // indirect + golang.org/x/term v0.15.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.8.1-0.20230428195545-5283a0178901 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect diff --git a/go.sum b/go.sum index b3c93a70b..085a77d13 100644 --- a/go.sum +++ b/go.sum @@ -100,6 +100,8 @@ github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/crowdsecurity/coraza/v3 v3.0.0-20231114091225-b0f8bc435a75 h1:Kp1sY2PE1H5nbr7xgAQeEWDqDW/o3HNL1rHvcVqzWT4= github.com/crowdsecurity/coraza/v3 v3.0.0-20231114091225-b0f8bc435a75/go.mod h1:jNww1Y9SujXQc89zDR+XOb70bkC7mZ6ep7iKhUBBsiI= +github.com/crowdsecurity/coraza/v3 v3.0.0-20231204125126-35deffad7734 h1:THMSMkBW/DLG5NvMAr/Mdg/eQOrEnMJ9Y+UdFG4yV8k= +github.com/crowdsecurity/coraza/v3 v3.0.0-20231204125126-35deffad7734/go.mod h1:jNww1Y9SujXQc89zDR+XOb70bkC7mZ6ep7iKhUBBsiI= github.com/crowdsecurity/dlog v0.0.0-20170105205344-4fb5f8204f26 h1:r97WNVC30Uen+7WnLs4xDScS/Ex988+id2k6mDf8psU= github.com/crowdsecurity/dlog v0.0.0-20170105205344-4fb5f8204f26/go.mod h1:zpv7r+7KXwgVUZnUNjyP22zc/D7LKjyoY02weH2RBbk= github.com/crowdsecurity/go-cs-lib v0.0.5 h1:eVLW+BRj3ZYn0xt5/xmgzfbbB8EBo32gM4+WpQQk2e8= @@ -754,6 +756,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -789,6 +793,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -841,6 +847,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -850,6 +858,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/pkg/acquisition/modules/waap/waap_runner.go b/pkg/acquisition/modules/waap/waap_runner.go index 3590f417d..2a9e53c29 100644 --- a/pkg/acquisition/modules/waap/waap_runner.go +++ b/pkg/acquisition/modules/waap/waap_runner.go @@ -3,6 +3,7 @@ package wafacquisition import ( "fmt" "os" + "slices" "time" "github.com/crowdsecurity/coraza/v3" @@ -191,6 +192,16 @@ func (r *WaapRunner) handleInBandInterrupt(request *waf.ParsedRequest) { r.WaapRuntime.Response.HTTPResponseCode = r.WaapRuntime.Config.BlockedHTTPCode r.WaapRuntime.Response.Action = r.WaapRuntime.DefaultRemediation + if _, ok := r.WaapRuntime.RemediationById[in.RuleID]; ok { + r.WaapRuntime.Response.Action = r.WaapRuntime.RemediationById[in.RuleID] + } + + for tag, remediation := range r.WaapRuntime.RemediationByTag { + if slices.Contains[[]string, string](in.Tags, tag) { + r.WaapRuntime.Response.Action = remediation + } + } + err = r.WaapRuntime.ProcessOnMatchRules(request, evt) if err != nil { r.logger.Errorf("unable to process OnMatch rules: %s", err) diff --git a/pkg/waf/waap.go b/pkg/waf/waap.go index f47f3312a..28abf6b04 100644 --- a/pkg/waf/waap.go +++ b/pkg/waf/waap.go @@ -84,6 +84,8 @@ type WaapRuntimeConfig struct { InBandRules []WaapCollection DefaultRemediation string + RemediationByTag map[string]string //Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME + RemediationById map[int]string CompiledOnLoad []Hook CompiledPreEval []Hook CompiledPostEval []Hook @@ -99,6 +101,13 @@ type WaapRuntimeConfig struct { //should we store matched rules here ? Logger *log.Entry + + //Set by on_load to ignore some rules on loading + disabledInBandRuleIds []int + disabledInBandRulesTags []string //Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME + + disabledOutOfBandRuleIds []int + disabledOutOfBandRulesTags []string //Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME } type WaapConfig struct { @@ -423,26 +432,46 @@ func (w *WaapRuntimeConfig) CancelEvent(params ...any) (any, error) { } // func (w *WaapRuntimeConfig) DisableInBandRuleByID(id int) error { +// Disable a rule at load time, meaning it will not run for any request func (w *WaapRuntimeConfig) DisableInBandRuleByID(params ...any) (any, error) { - panic("not implemented") + w.disabledInBandRuleIds = append(w.disabledInBandRuleIds, params[0].(int)) return nil, nil } -// func (w *WaapRuntimeConfig) DisableInBandRuleByTag(id int) error { +// func (w *WaapRuntimeConfig) DisableInBandRuleByName(name string) error { +// Disable a rule at load time, meaning it will not run for any request +func (w *WaapRuntimeConfig) DisableInBandRuleByName(params ...any) (any, error) { + tagValue := fmt.Sprintf("crowdsec-%s", params[0].(string)) + w.disabledInBandRulesTags = append(w.disabledInBandRulesTags, tagValue) + return nil, nil +} + +// func (w *WaapRuntimeConfig) DisableInBandRuleByTag(tag string) error { +// Disable a rule at load time, meaning it will not run for any request func (w *WaapRuntimeConfig) DisableInBandRuleByTag(params ...any) (any, error) { - panic("not implemented") + w.disabledInBandRulesTags = append(w.disabledInBandRulesTags, params[0].(string)) return nil, nil } -// func (w *WaapRuntimeConfig) DisableOutBandRuleByID(tag string) error { +// func (w *WaapRuntimeConfig) DisableOutBandRuleByID(id int) error { +// Disable a rule at load time, meaning it will not run for any request func (w *WaapRuntimeConfig) DisableOutBandRuleByID(params ...any) (any, error) { - panic("not implemented") + w.disabledOutOfBandRuleIds = append(w.disabledOutOfBandRuleIds, params[0].(int)) + return nil, nil +} + +// func (w *WaapRuntimeConfig) DisableOutBandRuleByName(name string) error { +// Disable a rule at load time, meaning it will not run for any request +func (w *WaapRuntimeConfig) DisableOutBandRuleByName(params ...any) (any, error) { + tagValue := fmt.Sprintf("crowdsec-%s", params[0].(string)) + w.disabledOutOfBandRulesTags = append(w.disabledOutOfBandRulesTags, tagValue) return nil, nil } // func (w *WaapRuntimeConfig) DisableOutBandRuleByTag(tag string) error { +// Disable a rule at load time, meaning it will not run for any request func (w *WaapRuntimeConfig) DisableOutBandRuleByTag(params ...any) (any, error) { - panic("not implemented") + w.disabledOutOfBandRulesTags = append(w.disabledOutOfBandRulesTags, params[0].(string)) return nil, nil } @@ -466,13 +495,37 @@ func (w *WaapRuntimeConfig) CancelAlert(params ...any) (any, error) { // func (w *WaapRuntimeConfig) SetActionByTag(tag string, action string) error { func (w *WaapRuntimeConfig) SetActionByTag(params ...any) (any, error) { - panic("not implemented") + if w.RemediationByTag == nil { + w.RemediationByTag = make(map[string]string) + } + tag := params[0].(string) + action := params[1].(string) + w.Logger.Debugf("setting action of %s to %s", tag, action) + w.RemediationByTag[tag] = action return nil, nil } // func (w *WaapRuntimeConfig) SetActionByID(id int, action string) error { func (w *WaapRuntimeConfig) SetActionByID(params ...any) (any, error) { - panic("not implemented") + if w.RemediationById == nil { + w.RemediationById = make(map[int]string) + } + id := params[0].(int) + action := params[1].(string) + w.Logger.Debugf("setting action of %d to %s", id, action) + w.RemediationById[id] = action + return nil, nil +} + +// func (w *WaapRuntimeConfig) SetActionByID(name string, action string) error { +func (w *WaapRuntimeConfig) SetActionByName(params ...any) (any, error) { + if w.RemediationByTag == nil { + w.RemediationByTag = make(map[string]string) + } + tag := fmt.Sprintf("crowdsec-%s", params[0].(string)) + action := params[1].(string) + w.Logger.Debugf("setting action of %s to %s", tag, action) + w.RemediationByTag[tag] = action return nil, nil } diff --git a/pkg/waf/waf_helpers.go b/pkg/waf/waf_helpers.go index 137f8544b..69b53df1e 100644 --- a/pkg/waf/waf_helpers.go +++ b/pkg/waf/waf_helpers.go @@ -26,6 +26,9 @@ func GetOnLoadEnv(w *WaapRuntimeConfig) map[string]interface{} { "RemoveOutBandRuleByID": w.DisableOutBandRuleByID, "RemoveInBandRuleByTag": w.DisableInBandRuleByTag, "RemoveOutBandRuleByTag": w.DisableOutBandRuleByTag, + "SetRemediationByTag": w.SetActionByTag, + "SetRemediationByID": w.SetActionByID, + "SetRemediationByName": w.SetActionByName, } } @@ -38,6 +41,7 @@ func GetPreEvalEnv(w *WaapRuntimeConfig, request *ParsedRequest) map[string]inte "RemoveOutBandRuleByID": w.RemoveOutbandRuleByID, "SetRemediationByTag": w.SetActionByTag, "SetRemediationByID": w.SetActionByID, + "SetRemediationByName": w.SetActionByName, } }