This commit is contained in:
Thibault Koechlin 2024-08-07 13:11:08 +02:00
parent 6bd4096a3e
commit 683011cff4
4 changed files with 68 additions and 1 deletions

View file

@ -660,6 +660,34 @@ func TestAppsecPreEvalHooks(t *testing.T) {
require.Equal(t, "foobar", responses[0].Action)
},
},
{
name: "pre_eval : SetRemediation (WAF rule in expr) + Bypass",
expected_load_ok: true,
inband_rules: []appsec_rule.CustomRule{
{
Name: "rulez",
Zones: []string{"ARGS"},
Variables: []string{"foo"},
Match: appsec_rule.Match{Type: "regex", Value: "^toto"},
Transform: []string{"lowercase"},
},
},
pre_eval: []appsec.Hook{
{Filter: "IsInBand && 1 == 1", Apply: []string{"SetRemediation('ban')", "SetReturnCode(403)"}},
},
input_request: appsec.ParsedRequest{
RemoteAddr: "1.2.3.4",
Method: "GET",
URI: "/urllll",
Args: url.Values{"bar": []string{"bar"}},
},
output_asserts: func(events []types.Event, responses []appsec.AppsecTempResponse, appsecResponse appsec.BodyResponse, statusCode int) {
require.Equal(t, appsec.BanRemediation, responses[0].Action)
//require.Equal(t, http.StatusForbidden, statusCode)
require.Equal(t, appsec.BanRemediation, appsecResponse.Action)
//require.Equal(t, http.StatusForbidden, appsecResponse.HTTPStatus)
},
},
}
for _, test := range tests {

View file

@ -128,6 +128,10 @@ func (r *AppsecRunner) processRequest(tx appsec.ExtendedTransaction, request *ap
}
}()
r.logger.Infof("(before pre_eval) planned remediation: %s", r.AppsecRuntime.Response.Action) //.Response.Action =
r.logger.Infof("(before pre_eval) planned resp code: %d", r.AppsecRuntime.Response.UserHTTPResponseCode) //.Response.Action =
r.logger.Infof("(before pre_eval) planned response: %+v", r.AppsecRuntime.Response) //.Response.Action =
//pre eval (expr) rules
err = r.AppsecRuntime.ProcessPreEvalRules(request)
if err != nil {
@ -135,6 +139,14 @@ func (r *AppsecRunner) processRequest(tx appsec.ExtendedTransaction, request *ap
//FIXME: should we abort here ?
}
r.logger.Infof("(after pre_eval) planned remediation: %s", r.AppsecRuntime.Response.Action) //.Response.Action =
r.logger.Infof("(after pre_eval) planned resp code: %d", r.AppsecRuntime.Response.UserHTTPResponseCode) //.Response.Action =
r.logger.Infof("(after pre_eval) planned response: %+v", r.AppsecRuntime.Response) //.Response.Action =
if r.AppsecRuntime.FlagSkipProcessing {
return nil
}
request.Tx.ProcessConnection(request.RemoteAddr, 0, "", 0)
for k, v := range request.Args {
@ -214,6 +226,8 @@ func (r *AppsecRunner) ProcessOutOfBandRules(request *appsec.ParsedRequest) erro
}
func (r *AppsecRunner) handleInBandInterrupt(request *appsec.ParsedRequest) {
r.logger.Infof("entering inband interrupt")
//create the associated event for crowdsec itself
evt, err := EventFromRequest(request, r.Labels)
if err != nil {
@ -322,6 +336,9 @@ func (r *AppsecRunner) handleRequest(request *appsec.ParsedRequest) {
logger.Errorf("unable to process InBand rules: %s", err)
return
}
logger.Infof("(after processInBand) planned remediation: %s", r.AppsecRuntime.Response.Action) //.Response.Action =
logger.Infof("(after processInBand) planned resp code: %d", r.AppsecRuntime.Response.UserHTTPResponseCode) //.Response.Action =
logger.Infof("(after processInBand) planned response: %+v", r.AppsecRuntime.Response) //.Response.Action =
// time spent to process in band rules
inBandParsingElapsed := time.Since(startInBandParsing)

View file

@ -87,7 +87,8 @@ type AppsecSubEngineOpts struct {
// runtime version of AppsecConfig
type AppsecRuntimeConfig struct {
Name string
Name string
OutOfBandRules []AppsecCollection
InBandRules []AppsecCollection
@ -107,6 +108,8 @@ type AppsecRuntimeConfig struct {
OutOfBandTx ExtendedTransaction //is it a good idea ?
InBandTx ExtendedTransaction //is it a good idea ?
Response AppsecTempResponse
FlagSkipProcessing bool
//should we store matched rules here ?
Logger *log.Entry
@ -603,6 +606,15 @@ func (w *AppsecRuntimeConfig) SetActionByName(name string, action string) error
return nil
}
func (w *AppsecRuntimeConfig) DenyRequest() error {
w.Logger.Debugf("setting action to deny")
w.Response.Action = BanRemediation
w.Response.BouncerHTTPResponseCode = w.Config.BouncerBlockedHTTPCode
w.Response.UserHTTPResponseCode = w.Config.UserBlockedHTTPCode
//w.Response.InBandInterrupt = true
return nil
}
func (w *AppsecRuntimeConfig) SetAction(action string) error {
//log.Infof("setting to %s", action)
w.Logger.Debugf("setting action to %s", action)
@ -616,6 +628,12 @@ func (w *AppsecRuntimeConfig) SetHTTPCode(code int) error {
return nil
}
func (w *AppsecRuntimeConfig) SkipProcessing() error {
w.Logger.Debugf("setting flag to skip normal processing")
w.FlagSkipProcessing = true
return nil
}
type BodyResponse struct {
Action string `json:"action"`
HTTPStatus int `json:"http_status"`

View file

@ -32,6 +32,10 @@ func GetPreEvalEnv(w *AppsecRuntimeConfig, request *ParsedRequest) map[string]in
"SetRemediationByTag": w.SetActionByTag,
"SetRemediationByID": w.SetActionByID,
"SetRemediationByName": w.SetActionByName,
"SetRemediation": w.SetAction,
"SetReturnCode": w.SetHTTPCode,
"SkipProcessing": w.SkipProcessing,
"DenyRequest": w.DenyRequest,
}
}