Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crowdsec-docs/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ const config: Config = {
editUrl: "https://github.com/crowdsecurity/crowdsec-docs/edit/main/crowdsec-docs/",
lastVersion: "current",
versions: {
"v1.6": {
"v1.7": {
banner: "none",
path: "/",
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
---
id: alerts_and_scenarios
title: Alerts & Scenarios
sidebar_position: 5
---

## 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](https://app.crowdsec.net/hub/author/crowdsecurity/configurations/appsec-logs) 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 to `appsec`
- `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) IP
- `evt.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 request
- `evt.Meta.rule_name` is set to the name of the triggered rule
- `evt.Meta.remediation_cmpt_ip` is set to the IP of the Remediation Component (Bouncer) that sent the HTTP request.

:::info
The [`crowdsecurity/appsec-logs` parser](https://app.crowdsec.net/hub/author/crowdsecurity/configurations/appsec-logs) 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](https://app.crowdsec.net/hub/author/crowdsecurity/configurations/appsec-vpatch) that will ban IPs triggering two distinct _In-Band_ rules:

```yaml title="/etc/crowdsec/scenarios/appsec-vpatch.yaml"
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
...
```

:::info
The [`crowdsecurity/appsec-vpatch` scenario](https://app.crowdsec.net/hub/author/crowdsecurity/configurations/appsec-vpatch) 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.

:::info
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:

```yaml title="/etc/crowdsec/appsec-rules/foobar-access.yaml"
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:

```yaml title="/etc/crowdsec/appsec-configs/appsec-oob.yaml"
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:

```yaml title="/etc/crowdsec/acquis.d/appsec.yaml"
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:

```yaml title="/etc/crowdsec/scenarios/foobar-enum.yaml"
type: leaky
format: 3.0
name: crowdsecurity/foobar-enum
description: "Ban IPs repeatedly 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
```

:::info
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:

```bash
$ 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.
65 changes: 65 additions & 0 deletions crowdsec-docs/versioned_docs/version-v1.7/appsec/benchmark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
id: benchmark
title: WAF Component Benchmark
sidebar_position: 80
---

<!--

- benchmark as previously done by KKA

- naked
- with a few vpatch rules
- with full CRS
- ?!

-->

The Application Security Component benchmarks have been run on a AWS EC2 Instance `t2.medium` (2vCPU/4GiB RAM).

All the benchmarks have been run with only one `routine` configured for the Application Security Component.

The benchmarks cover the following tests:

- Basic GET request:
- 5 concurrent connections / 1000 requests
- 15 concurrent connections / 1000 requests

<!--- POST request (50Ko body):
- 5 concurrent connections / 1000 requests
- 15 concurrent connections / 1000 requests
-->

Each test has been run with multiple cases:

- Application Security Component enabled but without any rules
- Application Security Component enabled with 100 vpatch rules (in in-band)
- Application Security Component enabled with all the CRS (in in-band)

On the system, we deployed:

- Openresty `1.21.4.3`
- CrowdSec `v1.6.0`
- cs-openresty-bouncer `v1.0.1`

## Basic GET request

### 5 concurrent connections / 1000 requests

![5 concurrent connections / 1000 requests](/img/appsec/bench/basic_get_appsec_one_routine_5_1000.png)

### 15 concurrent connections / 1000 requests

![15 concurrent connections / 1000 requests](/img/appsec/bench/basic_get_appsec_one_routine_15_1000.png)

<!--
## POST request (50Ko body)

### 5 concurrent connections / 1000 requests

![5 concurrent connections / 1000 requests](/img/appsec/bench/big_post_appsec_one_routine_5_1000.png)

### 15 concurrent connections / 1000 requests

![15 concurrent connections / 1000 requests](/img/appsec/bench/big_post_appsec_one_routine_15_1000.png)
-->
Loading