From 2481988f82f5e7927aab68a65b1a6178f44d360b Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Thu, 11 Jan 2024 13:55:56 +0100 Subject: [PATCH 1/4] inband -> outband typo --- pkg/acquisition/modules/appsec/appsec_runner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/acquisition/modules/appsec/appsec_runner.go b/pkg/acquisition/modules/appsec/appsec_runner.go index 5c72974c1c1..ef456ea3a20 100644 --- a/pkg/acquisition/modules/appsec/appsec_runner.go +++ b/pkg/acquisition/modules/appsec/appsec_runner.go @@ -272,7 +272,7 @@ func (r *AppsecRunner) handleOutBandInterrupt(request *appsec.ParsedRequest) { r.logger.Errorf("unable to accumulate tx to event : %s", err) } if in := request.Tx.Interruption(); in != nil { - r.logger.Debugf("inband rules matched : %d", in.RuleID) + r.logger.Debugf("outband rules matched : %d", in.RuleID) r.AppsecRuntime.Response.OutOfBandInterrupt = true err = r.AppsecRuntime.ProcessOnMatchRules(request, evt) From 30f7e9ccb9146ba78d769bbb80487357acd6a1fe Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Fri, 12 Jan 2024 10:21:07 +0100 Subject: [PATCH 2/4] always set status code to 403 if inband match, and send the user status code in the body --- pkg/acquisition/modules/appsec/appsec.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/acquisition/modules/appsec/appsec.go b/pkg/acquisition/modules/appsec/appsec.go index def6a6886ec..54e0da4469e 100644 --- a/pkg/acquisition/modules/appsec/appsec.go +++ b/pkg/acquisition/modules/appsec/appsec.go @@ -353,14 +353,18 @@ func (w *AppsecSource) appsecHandler(rw http.ResponseWriter, r *http.Request) { w.InChan <- parsedRequest response := <-parsedRequest.ResponseChannel + statusCode := http.StatusOK + if response.InBandInterrupt { + statusCode = http.StatusForbidden AppsecBlockCounter.With(prometheus.Labels{"source": parsedRequest.RemoteAddrNormalized, "appsec_engine": parsedRequest.AppsecEngine}).Inc() } appsecResponse := w.AppsecRuntime.GenerateResponse(response, logger) logger.Debugf("Response: %+v", appsecResponse) - rw.WriteHeader(appsecResponse.HTTPStatus) - body, err := json.Marshal(BodyResponse{Action: appsecResponse.Action}) + + rw.WriteHeader(statusCode) + body, err := json.Marshal(appsecResponse) if err != nil { logger.Errorf("unable to marshal response: %s", err) rw.WriteHeader(http.StatusInternalServerError) From d069d0da8b0d179042a9b210c830046636cc09ca Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Mon, 15 Jan 2024 09:55:19 +0100 Subject: [PATCH 3/4] don't update bouncer IP on HEAD requests --- pkg/apiserver/middlewares/v1/api_key.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/apiserver/middlewares/v1/api_key.go b/pkg/apiserver/middlewares/v1/api_key.go index 7e4df875c11..5a6d83d6d08 100644 --- a/pkg/apiserver/middlewares/v1/api_key.go +++ b/pkg/apiserver/middlewares/v1/api_key.go @@ -166,7 +166,8 @@ func (a *APIKey) MiddlewareFunc() gin.HandlerFunc { } } - if bouncer.IPAddress != c.ClientIP() && bouncer.IPAddress != "" { + //Don't update IP on HEAD request, as it's used by the appsec to check the validity of the API key provided + if bouncer.IPAddress != c.ClientIP() && bouncer.IPAddress != "" && c.Request.Method != http.MethodHead { log.Warningf("new IP address detected for bouncer '%s': %s (old: %s)", bouncer.Name, c.ClientIP(), bouncer.IPAddress) if err := a.DbClient.UpdateBouncerIP(c.ClientIP(), bouncer.ID); err != nil { logger.Errorf("Failed to update ip address for '%s': %s\n", bouncer.Name, err) From bc087bec8b2e4637f204e2099da0816ca13347d1 Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Mon, 15 Jan 2024 10:04:10 +0100 Subject: [PATCH 4/4] run PostEval hooks with defer --- pkg/acquisition/modules/appsec/appsec_runner.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/acquisition/modules/appsec/appsec_runner.go b/pkg/acquisition/modules/appsec/appsec_runner.go index ef456ea3a20..fa907fe4217 100644 --- a/pkg/acquisition/modules/appsec/appsec_runner.go +++ b/pkg/acquisition/modules/appsec/appsec_runner.go @@ -119,6 +119,11 @@ func (r *AppsecRunner) processRequest(tx appsec.ExtendedTransaction, request *ap defer func() { request.Tx.ProcessLogging() //We don't close the transaction here, as it will reset coraza internal state and break variable tracking + + err := r.AppsecRuntime.ProcessPostEvalRules(request) + if err != nil { + r.logger.Errorf("unable to process PostEval rules: %s", err) + } }() //pre eval (expr) rules @@ -182,11 +187,6 @@ func (r *AppsecRunner) processRequest(tx appsec.ExtendedTransaction, request *ap r.logger.Debugf("rules matched for body : %d", in.RuleID) } - err = r.AppsecRuntime.ProcessPostEvalRules(request) - if err != nil { - r.logger.Errorf("unable to process PostEval rules: %s", err) - } - return nil }