From a203d8ebbf904dd030b502d20fb2cfba7f2b4c8b Mon Sep 17 00:00:00 2001 From: blotus Date: Wed, 5 Mar 2025 16:04:16 +0100 Subject: [PATCH] appsec: handle SendAlert() properly for out of band matches (#3497) --- .../modules/appsec/appsec_hooks_test.go | 35 +++++++++++++++++++ .../modules/appsec/appsec_runner.go | 5 +-- pkg/acquisition/modules/appsec/utils.go | 4 +-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/pkg/acquisition/modules/appsec/appsec_hooks_test.go b/pkg/acquisition/modules/appsec/appsec_hooks_test.go index 46b2ed4d6..ae8498df7 100644 --- a/pkg/acquisition/modules/appsec/appsec_hooks_test.go +++ b/pkg/acquisition/modules/appsec/appsec_hooks_test.go @@ -332,6 +332,41 @@ func TestAppsecOnMatchHooks(t *testing.T) { require.Equal(t, appsec.CaptchaRemediation, responses[0].Action) }, }, + { + name: "on_match: SendAlert() with out-of-band rule", + expected_load_ok: true, + outofband_rules: []appsec_rule.CustomRule{ + { + Name: "rule42", + Zones: []string{"ARGS"}, + Variables: []string{"foo"}, + Match: appsec_rule.Match{Type: "regex", Value: "^toto"}, + Transform: []string{"lowercase"}, + }, + }, + DefaultRemediation: appsec.AllowRemediation, + on_match: []appsec.Hook{ + {Filter: "IsInBand == false", Apply: []string{"SendAlert()"}}, + }, + input_request: appsec.ParsedRequest{ + ClientIP: "1.2.3.4", + RemoteAddr: "1.2.3.4", + Method: "GET", + URI: "/urllll", + Args: url.Values{"foo": []string{"toto"}}, + }, + output_asserts: func(events []types.Event, responses []appsec.AppsecTempResponse, appsecResponse appsec.BodyResponse, statusCode int) { + require.Equal(t, appsec.AllowRemediation, appsecResponse.Action) + require.Equal(t, http.StatusOK, appsecResponse.HTTPStatus) + require.Equal(t, http.StatusOK, statusCode) + // We have both an event an overflow + require.Len(t, events, 2) + require.Equal(t, types.LOG, events[0].Type) + require.Equal(t, types.APPSEC, events[1].Type) + require.Nil(t, events[0].Overflow.Alert) + require.NotNil(t, events[1].Overflow.Alert) + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/pkg/acquisition/modules/appsec/appsec_runner.go b/pkg/acquisition/modules/appsec/appsec_runner.go index a21a16598..ad4bda6ea 100644 --- a/pkg/acquisition/modules/appsec/appsec_runner.go +++ b/pkg/acquisition/modules/appsec/appsec_runner.go @@ -286,7 +286,6 @@ func (r *AppsecRunner) handleInBandInterrupt(request *appsec.ParsedRequest) { r.outChan <- *appsecOvlfw } } - // Should the in band match trigger an event ? if r.AppsecRuntime.Response.SendEvent { r.outChan <- evt @@ -332,7 +331,9 @@ func (r *AppsecRunner) handleOutBandInterrupt(request *appsec.ParsedRequest) { r.logger.Errorf("unable to generate appsec event : %s", err) return } - r.outChan <- *appsecOvlfw + if appsecOvlfw != nil { + r.outChan <- *appsecOvlfw + } } } } diff --git a/pkg/acquisition/modules/appsec/utils.go b/pkg/acquisition/modules/appsec/utils.go index 65bb4601c..fece953b0 100644 --- a/pkg/acquisition/modules/appsec/utils.go +++ b/pkg/acquisition/modules/appsec/utils.go @@ -60,8 +60,8 @@ func AppsecEventGenerationGeoIPEnrich(src *models.Source) error { } func AppsecEventGeneration(inEvt types.Event, request *http.Request) (*types.Event, error) { - // if the request didnd't trigger inband rules, we don't want to generate an event to LAPI/CAPI - if !inEvt.Appsec.HasInBandMatches { + // if the request didn't trigger inband rules or out-of-band rules, we don't want to generate an event to LAPI/CAPI + if !inEvt.Appsec.HasInBandMatches && !inEvt.Appsec.HasOutBandMatches { return nil, nil }