This commit is contained in:
bui 2023-09-12 18:17:58 +02:00
parent 5a0b1b72d3
commit 1286efc74f
3 changed files with 66 additions and 84 deletions

View file

@ -1,31 +1,12 @@
Ongoing poc for Coraza Ongoing poc for Coraza WAAP
For config: # Configuration pieces
coraza_inband.conf: ## Acquisition
```shell
SecRuleEngine On
SecRule ARGS:id "@eq 0" "id:1, phase:1,deny, status:403,msg:'Invalid id',log,auditlog"
SecRequestBodyAccess On
SecRule REQUEST_BODY "@contains password" "id:2, phase:2,deny, status:403,msg:'Invalid request body',log,auditlog"
```
acquisition example:
coraza_outofband.conf: > `config/acquis.yaml` :
```shell
SecRuleEngine On
SecRule ARGS:id "@eq 1" "id:3,phase:1,log,msg:'Invalid id',log,auditlog"
SecRule ARGS:idd "@eq 2" "id:4,phase:1,log,msg:'Invalid id',log,auditlog"
SecRequestBodyAccess On
#We know that because we are not cloning the body in waf.go, the outofband rules cannot access body as it has been consumed.
#We are finding a way around this
#SecRule REQUEST_BODY "@contains totolol" "id:4, phase:2,deny,msg:'Invalid request body',log,auditlog"
#SecRule REQUEST_BODY "@contains password" "id:2, phase:2,deny, status:403,msg:'Invalid request body',log,auditlog"
```
acquis.yaml :
```yaml ```yaml
listen_addr: 127.0.0.1 listen_addr: 127.0.0.1
@ -34,71 +15,38 @@ path: /
source: waf source: waf
labels: labels:
type: waf type: waf
#routines: 1
waap_config: mytest
``` ```
Coraza parser: ## Waap config
The waap config defines what rules that will be loaded by a given waap engine (associated with an acquis).
> `config/waap_configs/mytest.yaml`
```yaml ```yaml
onsuccess: next_stage name: mytest.yaml
debug: true outofband_rules:
filter: "evt.Parsed.program == 'waf'" - crowdsec/crs-default
name: crowdsecurity/waf-logs inband_rules:
description: "Parse WAF logs" - crowdsec/vpatch-default
statics: default_remediation: block
- parsed: cloudtrail_parsed variables_tracking:
expression: UnmarshalJSON(evt.Line.Raw, evt.Unmarshaled, 'waf') - session_*
- meta: req_uuid # onload:
expression: evt.Unmarshaled.waf.req_uuid # - apply:
- meta: source_ip # - DisabledInBandRuleByID(1003)
expression: evt.Unmarshaled.waf.source_ip # pre_eval:
- meta: rule_id # - filter: evt.SourceIP == '1.3.4.5'
expression: evt.Unmarshaled.waf.rule_id # apply:
- meta: action # - DisableOutOfBandRuleByID(2302)
expression: evt.Unmarshaled.waf.rule_action
- meta: service
value: waf
- parsed: event_type
value: waf_match
``` ```
Coraza trigger scenario: # Waap Rules
For the above two to work, we need to have the two refered waap collection installed : `crowdsec/crs-default` and `crowdsec/vpatch-default`. You need to set hub_branch to ...
```yaml ```yaml
type: trigger cscli waf-rules install ...
filter: evt.Parsed.event_type == "waf_match" && evt.Unmarshaled.waf.rule_type == "inband" ```
debug: true
name: coroza-triggger
description: here we go
blackhole: 2m
labels:
type: exploit
remediation: true
groupby: "evt.Meta.source_ip"
```
Coraza leaky scenario:
```yaml
type: leaky
filter: evt.Parsed.event_type == "waf_match" && evt.Unmarshaled.waf.rule_type == "outofband"
debug: true
name: coroza-leaky
description: here we go
blackhole: 2m
leakspeed: 30s
capacity: 1
labels:
type: exploit
remediation: true
groupby: "evt.Meta.source_ip"
distinct: evt.Meta.rule_id
```
To be solved:
- We need to solve the body cloning issue
- Merge w/ hub

View file

@ -34,6 +34,7 @@ type WaapSourceConfig struct {
Routines int `yaml:"routines"` Routines int `yaml:"routines"`
Debug bool `yaml:"debug"` Debug bool `yaml:"debug"`
WaapConfig string `yaml:"waap_config"` WaapConfig string `yaml:"waap_config"`
WaapConfigPath string `yaml:"waap_config_path"`
configuration.DataSourceCommonCfg `yaml:",inline"` configuration.DataSourceCommonCfg `yaml:",inline"`
} }
@ -118,6 +119,24 @@ func (w *WaapSource) Configure(yamlConfig []byte, logger *log.Entry) error {
} }
w.InChan = make(chan waf.ParsedRequest) w.InChan = make(chan waf.ParsedRequest)
//let's load the associated waap_config:
if wc.WaapConfigPath != "" {
return fmt.Errorf("resolution gor waap_config not implemented yet")
} else if wc.WaapConfig != "" {
waapCfg := waf.WaapConfig{}
err := waapCfg.Load(wc.WaapConfig)
if err != nil {
return fmt.Errorf("unable to load waap_config : %s", err)
}
w.WaapRuntime, err = waapCfg.Build()
if err != nil {
return fmt.Errorf("unable to build waap_config : %s", err)
}
} else {
return fmt.Errorf("no waap_config provided")
}
w.WaapRunners = make([]WaapRunner, wc.Routines) w.WaapRunners = make([]WaapRunner, wc.Routines)
for nbRoutine := 0; nbRoutine < wc.Routines; nbRoutine++ { for nbRoutine := 0; nbRoutine < wc.Routines; nbRoutine++ {

View file

@ -2,12 +2,14 @@ package waf
import ( import (
"fmt" "fmt"
"os"
"regexp" "regexp"
"github.com/antonmedv/expr" "github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm" "github.com/antonmedv/expr/vm"
corazatypes "github.com/crowdsecurity/coraza/v3/types" corazatypes "github.com/crowdsecurity/coraza/v3/types"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
) )
type Hook struct { type Hook struct {
@ -63,6 +65,19 @@ type WaapConfig struct {
VariablesTracking []string `yaml:"variables_tracking"` VariablesTracking []string `yaml:"variables_tracking"`
} }
func (wc *WaapConfig) Load(file string) error {
yamlFile, err := os.ReadFile(file)
if err != nil {
return fmt.Errorf("unable to read file %s : %s", file, err)
}
err = yaml.UnmarshalStrict(yamlFile, wc)
if err != nil {
return fmt.Errorf("unable to parse yaml file %s : %s", file, err)
}
return nil
}
func (wc *WaapConfig) Build() (*WaapRuntimeConfig, error) { func (wc *WaapConfig) Build() (*WaapRuntimeConfig, error) {
ret := &WaapRuntimeConfig{} ret := &WaapRuntimeConfig{}
ret.Name = wc.Name ret.Name = wc.Name