AppSec Alerts & Scenarios
Generated Events Layout
HTTP requests that trigger In-Band or Out-Of-Band AppSec/WAF rules generate events. These events can trigger scenarios that react by banning or alerting when rules are matched.
The crowdsecurity/appsec-logs
parser is designed as a general-purpose tool to convert events into a format that is easier to process with scenarios.
The generated event looks like this:
evt.Meta.service
is set toappsec
evt.Meta.log_type
:appsec-block
for blocked requests (In-Band rule matched, for example)appsec-info
for requests that triggered Out-Of-Band rule (not blocked)
evt.Meta.source_ip
is set to the source (client) IPevt.Meta.target_host
is set to the FQDN if present (Host
header in the HTTP request)evt.Meta.target_uri
is set to the complete URI of the HTTP requestevt.Meta.rule_name
is set to the name of the triggered ruleevt.Meta.remediation_cmpt_ip
is set to the IP of the Remediation Component (Bouncer) that sent the HTTP request.
The crowdsecurity/appsec-logs
parser is already part of the generic AppSec/WAF collections and doesn't have to be manually installed.
Creating Scenario Based on AppSec/WAF Events
Triggering on In-Band Rules
A simple yexample is the crowdsecurity/appsec-vpatch
scenario that will ban IPs triggering two distinct In-Band rules:
type: leaky
name: crowdsecurity/appsec-vpatch
filter: "evt.Meta.log_type == 'appsec-block'"
distinct: evt.Meta.rule_name
leakspeed: "60s"
capacity: 1
groupby: evt.Meta.source_ip
...
The crowdsecurity/appsec-vpatch
scenario is already part of the generic AppSec/WAF collections, and doesn't have to be manually installed.
Triggering on Out-Of-Band Rules
Let's try to solve an imaginary scenario:
We aim to prevent users from enumerating certain URLs (specifically, those that begin with
/foobar/*
) when a particular HTTP header is present (something: *test*
). However, we want to impose this restriction only on users attempting to access two or more distinct/foobar/*
URLs while this header is set.
Keep in mind that Out-Of-Band rules will generate an event instead of blocking the HTTP Request.
The AppSec/WAF Rule
This is our AppSec/WAF rule:
name: crowdsecurity/foobar-access
description: "Detect access to foobar files with the something header set"
rules:
- zones:
- URI
transform:
- lowercase
match:
type: startsWith
value: /foobar/
- zones:
- HEADERS
variables:
- something
transform:
- lowercase
match:
type: contains
value: test
Let ensure it's loaded as an Out-Of-Band rule, first by creating a new appsec-config:
name: crowdsecurity/appsec-oob
default_remediation: ban
#Let's add our rule as an out-of-band rule
outofband_rules:
- crowdsecurity/foobar-access
And then make sure this appsec-config is loaded:
appsec_configs:
- crowdsecurity/appsec-default
- crowdsecurity/appsec-oob
labels:
type: appsec
listen_addr: 127.0.0.1:7422
source: appsec
The Scenario
We can now create a scenario that will trigger when a single IPs triggers this rule on distinct URLs:
type: leaky
format: 3.0
name: crowdsecurity/foobar-enum
description: "Ban IPs repeateadly triggering out of band rules"
filter: "evt.Meta.log_type == 'appsec-info' && evt.Meta.rule_name == 'crowdsecurity/foobar-access'"
distinct: evt.Meta.target_uri
leakspeed: "60s"
capacity: 1
groupby: evt.Meta.source_ip
blackhole: 1m
labels:
remediation: true
The filter
ensures only Out-Of-Band events generated by our scenario are picked up, while the capacity: 1
and distinct: evt.Meta.target_uri
will ensure that the IP has to trigger the rule on at least 2 distinct URLs to trigger the scenario.
Testing
Let's now test our setup:
$ curl -I localhost/foobar/1 -H 'something: test'
HTTP/1.1 404 Not Found
$ curl -I localhost/foobar/2 -H 'something: test'
HTTP/1.1 404 Not Found
$ curl -I localhost/foobar/3 -H 'something: test'
HTTP/1.1 403 Forbidden
And CrowdSec logs will show:
INFO[2024-12-02T15:28:16+01:00] Ip ::1 performed 'crowdsecurity/foobar-enum' (2 events over 4.780233613s) at 2024-12-02 14:28:16.858419797 +0000 UTC
INFO[2024-12-02T15:28:17+01:00] (test/crowdsec) crowdsecurity/foobar-enum by ip ::1 (/0) : 4h ban on Ip ::1
As expected, the first two requests were processed without being blocked. The second one triggered the scenario, resulting in the third request being blocked by the bouncer.