up
This commit is contained in:
parent
946fbbb8a2
commit
b1653aea63
|
@ -6,7 +6,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/crowdsecurity/coraza/v3"
|
||||
"github.com/crowdsecurity/coraza/v3/experimental"
|
||||
corazatypes "github.com/crowdsecurity/coraza/v3/types"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/waf"
|
||||
|
@ -77,7 +76,7 @@ func (r *WaapRunner) Init(datadir string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *WaapRunner) processRequest(tx experimental.FullTransaction, request *waf.ParsedRequest) error {
|
||||
func (r *WaapRunner) processRequest(tx waf.ExtendedTransaction, request *waf.ParsedRequest) error {
|
||||
var in *corazatypes.Interruption
|
||||
var err error
|
||||
request.Tx = tx
|
||||
|
@ -92,7 +91,14 @@ func (r *WaapRunner) processRequest(tx experimental.FullTransaction, request *wa
|
|||
//We don't close the transaction here, as it will reset coraza internal state and break variable tracking
|
||||
}()
|
||||
|
||||
request.Tx.ProcessConnection(request.RemoteAddr, 0, "", 0)
|
||||
//pre eval (expr) rules
|
||||
err = r.WaapRuntime.ProcessPreEvalRules(request)
|
||||
if err != nil {
|
||||
r.logger.Errorf("unable to process PreEval rules: %s", err)
|
||||
//FIXME: should we abort here ?
|
||||
}
|
||||
|
||||
request.Tx.Tx.ProcessConnection(request.RemoteAddr, 0, "", 0)
|
||||
|
||||
for k, v := range request.Args {
|
||||
for _, vv := range v {
|
||||
|
@ -151,14 +157,16 @@ func (r *WaapRunner) processRequest(tx experimental.FullTransaction, request *wa
|
|||
}
|
||||
|
||||
func (r *WaapRunner) ProcessInBandRules(request *waf.ParsedRequest) error {
|
||||
tx := r.WaapInbandEngine.NewTransactionWithID(request.UUID)
|
||||
err := r.processRequest(tx.(experimental.FullTransaction), request)
|
||||
tx := waf.NewExtendedTransaction(r.WaapInbandEngine, request.UUID)
|
||||
r.WaapRuntime.InBandTx = tx
|
||||
err := r.processRequest(tx, request)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *WaapRunner) ProcessOutOfBandRules(request *waf.ParsedRequest) error {
|
||||
tx := r.WaapOutbandEngine.NewTransactionWithID(request.UUID)
|
||||
err := r.processRequest(tx.(experimental.FullTransaction), request)
|
||||
tx := waf.NewExtendedTransaction(r.WaapInbandEngine, request.UUID)
|
||||
r.WaapRuntime.OutOfBandTx = tx
|
||||
err := r.processRequest(tx, request)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -180,14 +188,8 @@ func (r *WaapRunner) Run(t *tomb.Tomb) error {
|
|||
//to measure the time spent in the WAF
|
||||
startParsing := time.Now()
|
||||
|
||||
//pre eval (expr) rules
|
||||
err := r.WaapRuntime.ProcessPreEvalRules(request)
|
||||
if err != nil {
|
||||
r.logger.Errorf("unable to process PreEval rules: %s", err)
|
||||
continue
|
||||
}
|
||||
//inband WAAP rules
|
||||
err = r.ProcessInBandRules(&request)
|
||||
err := r.ProcessInBandRules(&request)
|
||||
if err != nil {
|
||||
r.logger.Errorf("unable to process InBand rules: %s", err)
|
||||
continue
|
||||
|
@ -206,7 +208,7 @@ func (r *WaapRunner) Run(t *tomb.Tomb) error {
|
|||
r.logger.Debugf("inband rules matched : %d", in.RuleID)
|
||||
r.WaapRuntime.Response.InBandInterrupt = true
|
||||
|
||||
err = r.WaapRuntime.ProcessOnMatchRules(request)
|
||||
err = r.WaapRuntime.ProcessOnMatchRules(&request)
|
||||
if err != nil {
|
||||
r.logger.Errorf("unable to process OnMatch rules: %s", err)
|
||||
continue
|
||||
|
@ -236,7 +238,7 @@ func (r *WaapRunner) Run(t *tomb.Tomb) error {
|
|||
if in := request.Tx.Interruption(); in != nil {
|
||||
r.logger.Debugf("outband rules matched : %d", in.RuleID)
|
||||
r.WaapRuntime.Response.OutOfBandInterrupt = true
|
||||
err = r.WaapRuntime.ProcessOnMatchRules(request)
|
||||
err = r.WaapRuntime.ProcessOnMatchRules(&request)
|
||||
if err != nil {
|
||||
r.logger.Errorf("unable to process OnMatch rules: %s", err)
|
||||
continue
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/crowdsecurity/coraza/v3/experimental"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
|
@ -74,7 +73,7 @@ type ParsedRequest struct {
|
|||
Body []byte
|
||||
TransferEncoding []string
|
||||
UUID string
|
||||
Tx experimental.FullTransaction
|
||||
Tx ExtendedTransaction
|
||||
ResponseChannel chan WaapTempResponse
|
||||
IsInBand bool
|
||||
IsOutBand bool
|
||||
|
|
|
@ -3,6 +3,8 @@ package waf
|
|||
import (
|
||||
"github.com/crowdsecurity/coraza/v3"
|
||||
"github.com/crowdsecurity/coraza/v3/experimental"
|
||||
"github.com/crowdsecurity/coraza/v3/experimental/plugins/plugintypes"
|
||||
"github.com/crowdsecurity/coraza/v3/types"
|
||||
)
|
||||
|
||||
type ExtendedTransaction struct {
|
||||
|
@ -24,3 +26,63 @@ func (t *ExtendedTransaction) RemoveRuleByIDWithError(id int) error {
|
|||
t.Tx.RemoveRuleByID(id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) IsRuleEngineOff() bool {
|
||||
return t.Tx.IsRuleEngineOff()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) ProcessLogging() {
|
||||
t.Tx.ProcessLogging()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) ProcessConnection(client string, cPort int, server string, sPort int) {
|
||||
t.Tx.ProcessConnection(client, cPort, server, sPort)
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) AddGetRequestArgument(name string, value string) {
|
||||
t.Tx.AddGetRequestArgument(name, value)
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) ProcessURI(uri string, method string, httpVersion string) {
|
||||
t.Tx.ProcessURI(uri, method, httpVersion)
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) AddRequestHeader(name string, value string) {
|
||||
t.Tx.AddRequestHeader(name, value)
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) SetServerName(name string) {
|
||||
t.Tx.SetServerName(name)
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) ProcessRequestHeaders() *types.Interruption {
|
||||
return t.Tx.ProcessRequestHeaders()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) ProcessRequestBody() (*types.Interruption, error) {
|
||||
return t.Tx.ProcessRequestBody()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) WriteRequestBody(body []byte) (*types.Interruption, int, error) {
|
||||
return t.Tx.WriteRequestBody(body)
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) Interruption() *types.Interruption {
|
||||
return t.Tx.Interruption()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) IsInterrupted() bool {
|
||||
return t.Tx.IsInterrupted()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) Variables() plugintypes.TransactionVariables {
|
||||
return t.Tx.Variables()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) MatchedRules() []types.MatchedRule {
|
||||
return t.Tx.MatchedRules()
|
||||
}
|
||||
|
||||
func (t *ExtendedTransaction) ID() string {
|
||||
return t.Tx.ID()
|
||||
}
|
||||
|
|
|
@ -21,18 +21,34 @@ type Hook struct {
|
|||
ApplyExpr []*vm.Program `yaml:"-"`
|
||||
}
|
||||
|
||||
// @tko : todo - debug mode
|
||||
func (h *Hook) Build() error {
|
||||
const (
|
||||
hookOnLoad = iota
|
||||
hookPreEval
|
||||
hookOnMatch
|
||||
)
|
||||
|
||||
// @tko : todo - debug mode
|
||||
func (h *Hook) Build(hookStage int) error {
|
||||
|
||||
ctx := map[string]interface{}{}
|
||||
switch hookStage {
|
||||
case hookOnLoad:
|
||||
ctx = GetOnLoadEnv(&WaapRuntimeConfig{})
|
||||
case hookPreEval:
|
||||
ctx = GetPreEvalEnv(&WaapRuntimeConfig{}, &ParsedRequest{})
|
||||
case hookOnMatch:
|
||||
ctx = GetOnMatchEnv(&WaapRuntimeConfig{}, &ParsedRequest{})
|
||||
}
|
||||
opts := GetExprWAFOptions(ctx)
|
||||
if h.Filter != "" {
|
||||
program, err := expr.Compile(h.Filter) //FIXME: opts
|
||||
program, err := expr.Compile(h.Filter, opts...) //FIXME: opts
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to compile filter %s : %w", h.Filter, err)
|
||||
}
|
||||
h.FilterExpr = program
|
||||
}
|
||||
for _, apply := range h.Apply {
|
||||
program, err := expr.Compile(apply, GetExprWAFOptions(GetHookEnv(&WaapRuntimeConfig{}, ParsedRequest{}))...)
|
||||
program, err := expr.Compile(apply, opts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to compile apply %s : %w", apply, err)
|
||||
}
|
||||
|
@ -204,7 +220,7 @@ func (wc *WaapConfig) Build() (*WaapRuntimeConfig, error) {
|
|||
|
||||
//load hooks
|
||||
for _, hook := range wc.OnLoad {
|
||||
err := hook.Build()
|
||||
err := hook.Build(hookOnLoad)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to build on_load hook : %s", err)
|
||||
}
|
||||
|
@ -212,7 +228,7 @@ func (wc *WaapConfig) Build() (*WaapRuntimeConfig, error) {
|
|||
}
|
||||
|
||||
for _, hook := range wc.PreEval {
|
||||
err := hook.Build()
|
||||
err := hook.Build(hookPreEval)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to build pre_eval hook : %s", err)
|
||||
}
|
||||
|
@ -220,7 +236,7 @@ func (wc *WaapConfig) Build() (*WaapRuntimeConfig, error) {
|
|||
}
|
||||
|
||||
for _, hook := range wc.OnMatch {
|
||||
err := hook.Build()
|
||||
err := hook.Build(hookOnMatch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to build on_match hook : %s", err)
|
||||
}
|
||||
|
@ -243,7 +259,7 @@ func (w *WaapRuntimeConfig) ProcessOnLoadRules() error {
|
|||
if rule.FilterExpr != nil {
|
||||
output, err := expr.Run(rule.FilterExpr, GetOnLoadEnv(w))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to run filter %s : %w", rule.Filter, err)
|
||||
return fmt.Errorf("unable to run waap on_load filter %s : %w", rule.Filter, err)
|
||||
}
|
||||
switch t := output.(type) {
|
||||
case bool:
|
||||
|
@ -259,7 +275,7 @@ func (w *WaapRuntimeConfig) ProcessOnLoadRules() error {
|
|||
for _, applyExpr := range rule.ApplyExpr {
|
||||
_, err := expr.Run(applyExpr, GetOnLoadEnv(w))
|
||||
if err != nil {
|
||||
log.Errorf("unable to apply filter: %s", err)
|
||||
log.Errorf("unable to apply waap on_load expr: %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -267,13 +283,13 @@ func (w *WaapRuntimeConfig) ProcessOnLoadRules() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (w *WaapRuntimeConfig) ProcessOnMatchRules(request ParsedRequest) error {
|
||||
func (w *WaapRuntimeConfig) ProcessOnMatchRules(request *ParsedRequest) error {
|
||||
|
||||
for _, rule := range w.CompiledOnMatch {
|
||||
if rule.FilterExpr != nil {
|
||||
output, err := expr.Run(rule.FilterExpr, GetOnMatchEnv(w, request))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to run filter %s : %w", rule.Filter, err)
|
||||
return fmt.Errorf("unable to run waap on_match filter %s : %w", rule.Filter, err)
|
||||
}
|
||||
switch t := output.(type) {
|
||||
case bool:
|
||||
|
@ -289,7 +305,7 @@ func (w *WaapRuntimeConfig) ProcessOnMatchRules(request ParsedRequest) error {
|
|||
for _, applyExpr := range rule.ApplyExpr {
|
||||
_, err := expr.Run(applyExpr, GetOnMatchEnv(w, request))
|
||||
if err != nil {
|
||||
log.Errorf("unable to apply filter: %s", err)
|
||||
log.Errorf("unable to apply waap on_match expr: %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -297,12 +313,12 @@ func (w *WaapRuntimeConfig) ProcessOnMatchRules(request ParsedRequest) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (w *WaapRuntimeConfig) ProcessPreEvalRules(request ParsedRequest) error {
|
||||
func (w *WaapRuntimeConfig) ProcessPreEvalRules(request *ParsedRequest) error {
|
||||
for _, rule := range w.CompiledPreEval {
|
||||
if rule.FilterExpr != nil {
|
||||
output, err := expr.Run(rule.FilterExpr, GetPreEvalEnv(w, request))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to run filter %s : %w", rule.Filter, err)
|
||||
return fmt.Errorf("unable to run waap pre_eval filter %s : %w", rule.Filter, err)
|
||||
}
|
||||
switch t := output.(type) {
|
||||
case bool:
|
||||
|
@ -319,7 +335,7 @@ func (w *WaapRuntimeConfig) ProcessPreEvalRules(request ParsedRequest) error {
|
|||
for _, applyExpr := range rule.ApplyExpr {
|
||||
_, err := expr.Run(applyExpr, GetPreEvalEnv(w, request))
|
||||
if err != nil {
|
||||
log.Errorf("unable to apply filter: %s", err)
|
||||
log.Errorf("unable to apply waap pre_eval expr: %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +359,13 @@ func (w *WaapRuntimeConfig) RemoveInbandRuleByID(params ...any) (any, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// func (w *WaapRuntimeConfig) RemoveOutbandRuleByID(id int) error {
|
||||
func (w *WaapRuntimeConfig) RemoveOutbandRuleByID(params ...any) (any, error) {
|
||||
id := params[0].(int)
|
||||
_ = w.OutOfBandTx.RemoveRuleByIDWithError(id)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (w *WaapRuntimeConfig) CancelEvent(params ...any) (any, error) {
|
||||
w.Response.SendEvent = false
|
||||
return nil, nil
|
||||
|
@ -399,13 +422,6 @@ func (w *WaapRuntimeConfig) SetActionByID(params ...any) (any, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// func (w *WaapRuntimeConfig) RemoveOutbandRuleByID(id int) error {
|
||||
func (w *WaapRuntimeConfig) RemoveOutbandRuleByID(params ...any) (any, error) {
|
||||
id := params[0].(int)
|
||||
_ = w.OutOfBandTx.RemoveRuleByIDWithError(id)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// func (w *WaapRuntimeConfig) SetAction(action string) error {
|
||||
func (w *WaapRuntimeConfig) SetAction(params ...any) (any, error) {
|
||||
//log.Infof("setting to %s", action)
|
||||
|
|
|
@ -8,7 +8,26 @@ type exprCustomFunc struct {
|
|||
signature []interface{}
|
||||
}
|
||||
|
||||
var onLoadExprFuncs = []exprCustomFunc{}
|
||||
/*
|
||||
func GetOnLoadEnv(w *WaapRuntimeConfig) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"DisableInBandRuleByID": w.DisableInBandRuleByID,
|
||||
"DisableOutBandRuleByID": w.DisableOutBandRuleByID,
|
||||
"DisableInBandRuleByTag": w.DisableInBandRuleByTag,
|
||||
"DisableOutBandRuleByTag": w.DisableOutBandRuleByTag,
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*var onLoadExprFuncs = []exprCustomFunc{
|
||||
{
|
||||
name: "DisableInBandRuleByID",
|
||||
function: w.DisableInBandRuleByID,
|
||||
signature: []interface{}{
|
||||
new(func(int) error),
|
||||
},
|
||||
},
|
||||
}*/
|
||||
|
||||
var preEvalExprFuncs = []exprCustomFunc{}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ func GetExprWAFOptions(ctx map[string]interface{}) []expr.Option {
|
|||
}
|
||||
|
||||
func GetOnLoadEnv(w *WaapRuntimeConfig) map[string]interface{} {
|
||||
//FIXME: use expr.Function instead of this
|
||||
return map[string]interface{}{
|
||||
"DisableInBandRuleByID": w.DisableInBandRuleByID,
|
||||
"DisableOutBandRuleByID": w.DisableOutBandRuleByID,
|
||||
|
@ -40,7 +41,8 @@ func GetOnLoadEnv(w *WaapRuntimeConfig) map[string]interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
func GetPreEvalEnv(w *WaapRuntimeConfig, request ParsedRequest) map[string]interface{} {
|
||||
func GetPreEvalEnv(w *WaapRuntimeConfig, request *ParsedRequest) map[string]interface{} {
|
||||
//FIXME: use expr.Function instead of this
|
||||
return map[string]interface{}{
|
||||
"IsInBand": request.IsInBand,
|
||||
"IsOutBand": request.IsOutBand,
|
||||
|
@ -51,7 +53,8 @@ func GetPreEvalEnv(w *WaapRuntimeConfig, request ParsedRequest) map[string]inter
|
|||
}
|
||||
}
|
||||
|
||||
func GetOnMatchEnv(w *WaapRuntimeConfig, request ParsedRequest) map[string]interface{} {
|
||||
func GetOnMatchEnv(w *WaapRuntimeConfig, request *ParsedRequest) map[string]interface{} {
|
||||
//FIXME: use expr.Function instead of this
|
||||
return map[string]interface{}{
|
||||
"req": request,
|
||||
"IsInBand": request.IsInBand,
|
||||
|
|
Loading…
Reference in a new issue