Browse Source

add SetRemediationByTag/Name/ID

Sebastien Blot 1 year ago
parent
commit
6fb965bb3f
5 changed files with 91 additions and 13 deletions
  1. 5 5
      go.mod
  2. 10 0
      go.sum
  3. 11 0
      pkg/acquisition/modules/waap/waap_runner.go
  4. 61 8
      pkg/waf/waap.go
  5. 4 0
      pkg/waf/waf_helpers.go

+ 5 - 5
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

+ 10 - 0
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=

+ 11 - 0
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)

+ 61 - 8
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) 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(id int) error {
+// 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
 }
 

+ 4 - 0
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,
 	}
 }