From 792961d757e87cbe032a4bd106bb1025b784d580 Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Mon, 24 Jul 2023 14:50:08 +0200 Subject: [PATCH] wip --- pkg/acquisition/modules/waf/utils.go | 10 ++++ pkg/acquisition/modules/waf/waf.go | 19 ++------ pkg/types/event.go | 69 +++++++++++++++++++--------- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/pkg/acquisition/modules/waf/utils.go b/pkg/acquisition/modules/waf/utils.go index 9c24623e0..49c5bf71f 100644 --- a/pkg/acquisition/modules/waf/utils.go +++ b/pkg/acquisition/modules/waf/utils.go @@ -4,7 +4,9 @@ import ( "fmt" "time" + "github.com/crowdsecurity/coraza/v3/collection" "github.com/crowdsecurity/coraza/v3/experimental" + "github.com/crowdsecurity/coraza/v3/types/variables" "github.com/crowdsecurity/crowdsec/pkg/types" "github.com/crowdsecurity/crowdsec/pkg/waf" "github.com/prometheus/client_golang/prometheus" @@ -71,6 +73,14 @@ func (r *WafRunner) AccumulateTxToEvent(tx experimental.FullTransaction, kind st evt.Meta["waap_interrupted"] = "1" evt.Meta["waap_action"] = tx.Interruption().Action } + + tx.Variables().All(func(v variables.RuleVariable, col collection.Collection) bool { + for _, variable := range col.FindAll() { + r.logger.Infof("%s.%s = %s", variable.Variable().Name(), variable.Key(), variable.Value()) + } + return true + }) + r.logger.Infof("variables addr in AccumulateTxToEvent: %p", tx.Variables()) //log.Infof("variables: %s", spew.Sdump(tx.Variables())) //log.Infof("tx variables: %+v", tx.Collection(variables.TX)) diff --git a/pkg/acquisition/modules/waf/waf.go b/pkg/acquisition/modules/waf/waf.go index 06e0e0683..749576314 100644 --- a/pkg/acquisition/modules/waf/waf.go +++ b/pkg/acquisition/modules/waf/waf.go @@ -11,10 +11,8 @@ import ( "github.com/antonmedv/expr" "github.com/crowdsecurity/coraza/v3" - "github.com/crowdsecurity/coraza/v3/collection" "github.com/crowdsecurity/coraza/v3/experimental" corazatypes "github.com/crowdsecurity/coraza/v3/types" - "github.com/crowdsecurity/coraza/v3/types/variables" "github.com/crowdsecurity/crowdsec/pkg/acquisition/configuration" "github.com/crowdsecurity/crowdsec/pkg/types" "github.com/crowdsecurity/crowdsec/pkg/waf" @@ -338,7 +336,8 @@ func (r *WafRunner) processReqWithEngine(tx experimental.FullTransaction, parsed defer func() { tx.ProcessLogging() - tx.Close() + //Dont close the transaction here: we still need access to the variables afterwards + //tx.Close() }() //this method is not exported by coraza, so we have to do it ourselves. @@ -371,17 +370,6 @@ func (r *WafRunner) processReqWithEngine(tx experimental.FullTransaction, parsed in = tx.ProcessRequestHeaders() - for _, v := range tx.Collection(variables.TX).FindAll() { - log.Infof("tx variable: %s | %s", v.Key(), v.Value()) - } - - tx.Variables().All(func(v variables.RuleVariable, col collection.Collection) bool { - log.Infof("Collection: %s", col.Name()) - log.Infof("Variable: %s", v.Name()) - //collect := tx.Collection(col) - return true - }) - //spew.Dump(in) //spew.Dump(tx.MatchedRules()) @@ -569,6 +557,7 @@ func (r *WafRunner) Run(t *tomb.Tomb) error { LogWaapEvent(evt) r.outChan <- *evt } + expTx.Close() outBandStart := time.Now() // Process outBand @@ -595,8 +584,8 @@ func (r *WafRunner) Run(t *tomb.Tomb) error { } LogWaapEvent(evt) r.outChan <- *evt - } + expTx.Close() //measure the full time spent in the WAF totalElapsed := time.Since(startParsing) WafGlobalParsingHistogram.With(prometheus.Labels{"source": request.RemoteAddr}).Observe(totalElapsed.Seconds()) diff --git a/pkg/types/event.go b/pkg/types/event.go index b51d12916..0405c3466 100644 --- a/pkg/types/event.go +++ b/pkg/types/event.go @@ -3,6 +3,7 @@ package types import ( "fmt" "regexp" + "strings" "time" log "github.com/sirupsen/logrus" @@ -27,8 +28,12 @@ len(evt.Waf.ByTagRx("*CVE*").ByConfidence("high").ByAction("block")) > 1 */ -type WaapEvent []map[string]interface{} +type MatchedRules []map[string]interface{} +type WaapEvent struct { + MatchedRules + Vars map[string]string +} type Field string func (f Field) String() string { @@ -49,8 +54,28 @@ const ( Kind Field = "kind" ) +func (w WaapEvent) GetVar(varName string) string { + if w.Vars == nil { + return "" + } + parsed := strings.Split(varName, ".") + if len(parsed) == 1 { + //no subkey + return w.Vars[varName] + } else if len(parsed) == 2 { + //subkey + if w.Vars[parsed[0]] == "" { + return "" + } + return w.Vars[parsed[0]][parsed[1]] + } + log.Warningf("invalid variable name %s", varName) + return "" + +} + // getters -func (w WaapEvent) GetField(field Field) []interface{} { +func (w MatchedRules) GetField(field Field) []interface{} { ret := make([]interface{}, 0) for _, rule := range w { ret = append(ret, rule[field.String()]) @@ -58,21 +83,21 @@ func (w WaapEvent) GetField(field Field) []interface{} { return ret } -func (w WaapEvent) GetURI() string { +func (w MatchedRules) GetURI() string { for _, rule := range w { return rule["uri"].(string) } return "" } -func (w WaapEvent) GetMethod() string { +func (w MatchedRules) GetMethod() string { for _, rule := range w { return rule["method"].(string) } return "" } -func (w WaapEvent) GetRuleIDs() []int { +func (w MatchedRules) GetRuleIDs() []int { ret := make([]int, 0) for _, rule := range w { ret = append(ret, rule["id"].(int)) @@ -80,7 +105,7 @@ func (w WaapEvent) GetRuleIDs() []int { return ret } -func (w WaapEvent) Kinds() []string { +func (w MatchedRules) Kinds() []string { ret := make([]string, 0) for _, rule := range w { exists := false @@ -98,8 +123,8 @@ func (w WaapEvent) Kinds() []string { } // filters -func (w WaapEvent) ByID(id int) WaapEvent { - waap := WaapEvent{} +func (w MatchedRules) ByID(id int) MatchedRules { + waap := MatchedRules{} for _, rule := range w { if rule["id"] == id { @@ -109,8 +134,8 @@ func (w WaapEvent) ByID(id int) WaapEvent { return waap } -func (w WaapEvent) ByKind(kind string) WaapEvent { - waap := WaapEvent{} +func (w MatchedRules) ByKind(kind string) MatchedRules { + waap := MatchedRules{} for _, rule := range w { if rule["kind"] == kind { waap = append(waap, rule) @@ -119,8 +144,8 @@ func (w WaapEvent) ByKind(kind string) WaapEvent { return waap } -func (w WaapEvent) ByTags(match []string) WaapEvent { - waap := WaapEvent{} +func (w MatchedRules) ByTags(match []string) MatchedRules { + waap := MatchedRules{} for _, rule := range w { for _, tag := range rule["tags"].([]string) { for _, match_tag := range match { @@ -134,8 +159,8 @@ func (w WaapEvent) ByTags(match []string) WaapEvent { return waap } -func (w WaapEvent) ByTag(match string) WaapEvent { - waap := WaapEvent{} +func (w MatchedRules) ByTag(match string) MatchedRules { + waap := MatchedRules{} for _, rule := range w { for _, tag := range rule["tags"].([]string) { if tag == match { @@ -147,8 +172,8 @@ func (w WaapEvent) ByTag(match string) WaapEvent { return waap } -func (w WaapEvent) ByTagRx(rx string) WaapEvent { - waap := WaapEvent{} +func (w MatchedRules) ByTagRx(rx string) MatchedRules { + waap := MatchedRules{} re := regexp.MustCompile(rx) if re == nil { return waap @@ -165,9 +190,9 @@ func (w WaapEvent) ByTagRx(rx string) WaapEvent { return waap } -func (w WaapEvent) ByDisruptiveness(is bool) WaapEvent { +func (w MatchedRules) ByDisruptiveness(is bool) MatchedRules { log.Infof("%s", w) - wap := WaapEvent{} + wap := MatchedRules{} for _, rule := range w { if rule["disruptive"] == is { wap = append(wap, rule) @@ -178,8 +203,8 @@ func (w WaapEvent) ByDisruptiveness(is bool) WaapEvent { return wap } -func (w WaapEvent) BySeverity(severity string) WaapEvent { - wap := WaapEvent{} +func (w MatchedRules) BySeverity(severity string) MatchedRules { + wap := MatchedRules{} for _, rule := range w { if rule["severity"] == severity { wap = append(wap, rule) @@ -189,8 +214,8 @@ func (w WaapEvent) BySeverity(severity string) WaapEvent { return wap } -func (w WaapEvent) ByAccuracy(accuracy string) WaapEvent { - wap := WaapEvent{} +func (w MatchedRules) ByAccuracy(accuracy string) MatchedRules { + wap := MatchedRules{} for _, rule := range w { if rule["accuracy"] == accuracy { wap = append(wap, rule)