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:
```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
acquisition example:
coraza_outofband.conf:
```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 :
> `config/acquis.yaml` :
```yaml
listen_addr: 127.0.0.1
@ -34,71 +15,38 @@ path: /
source: waf
labels:
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
onsuccess: next_stage
debug: true
filter: "evt.Parsed.program == 'waf'"
name: crowdsecurity/waf-logs
description: "Parse WAF logs"
statics:
- parsed: cloudtrail_parsed
expression: UnmarshalJSON(evt.Line.Raw, evt.Unmarshaled, 'waf')
- meta: req_uuid
expression: evt.Unmarshaled.waf.req_uuid
- meta: source_ip
expression: evt.Unmarshaled.waf.source_ip
- meta: rule_id
expression: evt.Unmarshaled.waf.rule_id
- meta: action
expression: evt.Unmarshaled.waf.rule_action
- meta: service
value: waf
- parsed: event_type
value: waf_match
name: mytest.yaml
outofband_rules:
- crowdsec/crs-default
inband_rules:
- crowdsec/vpatch-default
default_remediation: block
variables_tracking:
- session_*
# onload:
# - apply:
# - DisabledInBandRuleByID(1003)
# pre_eval:
# - filter: evt.SourceIP == '1.3.4.5'
# apply:
# - DisableOutOfBandRuleByID(2302)
```
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
type: trigger
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
cscli waf-rules install ...
```

View file

@ -34,6 +34,7 @@ type WaapSourceConfig struct {
Routines int `yaml:"routines"`
Debug bool `yaml:"debug"`
WaapConfig string `yaml:"waap_config"`
WaapConfigPath string `yaml:"waap_config_path"`
configuration.DataSourceCommonCfg `yaml:",inline"`
}
@ -118,6 +119,24 @@ func (w *WaapSource) Configure(yamlConfig []byte, logger *log.Entry) error {
}
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)
for nbRoutine := 0; nbRoutine < wc.Routines; nbRoutine++ {

View file

@ -2,12 +2,14 @@ package waf
import (
"fmt"
"os"
"regexp"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
corazatypes "github.com/crowdsecurity/coraza/v3/types"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
)
type Hook struct {
@ -63,6 +65,19 @@ type WaapConfig struct {
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) {
ret := &WaapRuntimeConfig{}
ret.Name = wc.Name