Skip to content

Commit 9e0f1f9

Browse files
authored
Merge pull request #855 from julienloizelet/feat/wordpress-appsec-quickstart
feat(appsec): Add quickstart for WordPress
2 parents b3cc726 + 09c5ba4 commit 9e0f1f9

File tree

3 files changed

+320
-0
lines changed

3 files changed

+320
-0
lines changed

crowdsec-docs/docs/appsec/intro.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ You can follow our quick start guides depending on your web server:
6666

6767
- [Nginx/OpenResty](/appsec/quickstart/nginxopenresty.mdx)
6868
- [Traefik](/appsec/quickstart/traefik.mdx)
69+
- [WordPress](/appsec/quickstart/wordpress.mdx)
6970
- [CrowdSec WAF with Nginx Reverse Proxy](/u/user_guides/waf_rp_howto)
7071

7172
Or consider learning more about the AppSec capabilities:
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
---
2+
id: wordpress
3+
title: WordPress
4+
---
5+
6+
import Tabs from '@theme/Tabs';
7+
import TabItem from '@theme/TabItem';
8+
import CodeBlock from '@theme/CodeBlock';
9+
import UnderlineTooltip from '@site/src/components/underline-tooltip';
10+
11+
# CrowdSec WAF QuickStart for WordPress
12+
13+
## Objectives
14+
15+
The goal of this quickstart is to set up the [AppSec Component](/appsec/intro.md#introduction) to safeguard web applications running on [WordPress](https://wordpress.org) sites.
16+
17+
We'll deploy a [set of rules](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-virtual-patching) designed to block [well-known attacks](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-generic-rules) and [currently exploited vulnerabilities](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-virtual-patching).
18+
19+
Additionally, we'll show how to monitor these alerts through the [console](https://app.crowdsec.net/).
20+
21+
## Pre-requisites
22+
23+
1. If you're new to the [AppSec Component](/appsec/intro.md#introduction) or **W**eb **A**pplication **F**irewalls, start with the [Introduction](/appsec/intro.md#introduction) for a better understanding.
24+
25+
2. It's assumed that you have already installed:
26+
- **CrowdSec [Security Engine](intro.mdx)**: for installation, refer to the [QuickStart guide](/u/getting_started/installation/linux). The AppSec Component, which analyzes HTTP requests, is included within the security engine as a [Acquisition](/log_processor/data_sources/appsec.md).
27+
- **WordPress [Remediation Component](/u/bouncers/intro)**: installation instructions are available in the [WordPress bouncer guide](/u/bouncers/wordpress). The CrowdSec WordPress plugin enables you to protect your WordPress site against malicious traffic using CrowdSec's advanced threat detection and blocklist capabilities.
28+
29+
This component intercepts HTTP requests at the WordPress level and forwards them to the AppSec Component for analysis and action.
30+
31+
32+
## AppSec Component Setup
33+
34+
### Collection installation
35+
36+
To begin setting up the AppSec Component, the initial step is to install a relevant set of rules.
37+
38+
We will utilize the [`crowdsecurity/appsec-virtual-patching`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-virtual-patching) collection, which offers a wide range of rules aimed at identifying and preventing the exploitation of known vulnerabilities.
39+
40+
This <UnderlineTooltip tooltip="Collections are bundle of parsers, scenarios, postoverflows that form a coherent package.">collection</UnderlineTooltip> is regularly updated to include protection against newly discovered vulnerabilities. Upon installation, it receives automatic daily updates to ensure your protection is always current.
41+
Furthermore we also install the [`crowdsecurity/appsec-generic-rules`](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-generic-rules) collection. This collection contains detection scenarios for generic attack vectors. It provides some protection in cases where specific scenarios for vulnerabilities do not exist (yet).
42+
43+
On the machine where the Security Engine is installed, just execute the following command:
44+
45+
:::info
46+
You can always view the content of a [collection on the hub](https://app.crowdsec.net/hub/author/crowdsecurity/collections/appsec-virtual-patching)
47+
:::
48+
49+
```bash
50+
sudo cscli collections install crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules
51+
```
52+
53+
Executing this command will install the following items:
54+
55+
- The [*AppSec Rules*](/appsec/rules_syntax.md) contain the definition of malevolent requests to be matched and stopped
56+
- The [*AppSec Configuration*](/appsec/configuration.md#appsec-configuration) links together a set of rules to provide a coherent set
57+
- The <UnderlineTooltip tooltip="YAML files that extract relevant data from logs, such as IP addresses, timestamps, or request paths.">CrowdSec Parser</UnderlineTooltip> and <UnderlineTooltip tooltip="Behavioral rules written in a domain-specific language that define what malicious activity looks like, such as multiple failed logins in a short time.">CrowdSec Scenario(s)</UnderlineTooltip> bans for a longer duration repeating offenders
58+
59+
### Setup the Acquisition
60+
61+
Having installed the required components, it's time to configure the CrowdSec <UnderlineTooltip tooltip="Acquisition files tell CrowdSec where to find logs and which application they belong to.">Acquisition</UnderlineTooltip> to expose the Application Security Component to our WordPress site. This configuration allows our WordPress site to send requests to the AppSec Component for evaluation and decision-making.
62+
63+
Steps:
64+
1. Create the `/etc/crowdsec/acquis.d/` directory (if it doesn't exist on your machine)
65+
```bash
66+
mkdir -p /etc/crowdsec/acquis.d/
67+
```
68+
2. Create a file `/etc/crowdsec/acquis.d/appsec.yaml` with the following content:
69+
```yaml title="/etc/crowdsec/acquis.d/appsec.yaml"
70+
appsec_config: crowdsecurity/appsec-default
71+
labels:
72+
type: appsec
73+
listen_addr: 127.0.0.1:7422
74+
source: appsec
75+
```
76+
77+
The two important directives in this configuration file are:
78+
79+
- `appsec_config` is the name of the [*AppSec Configuration*](appsec/configuration.md#appsec-configuration) that was included in the <UnderlineTooltip tooltip="Collections are bundle of parsers, scenarios, postoverflows that form a coherent package.">Collection</UnderlineTooltip> we just installed.
80+
- the `listen_addr` is the IP and port the AppSec Component will listen to.
81+
82+
:::warning
83+
We do not recommend exposing the AppSec Component to the internet. It should only be accessible from the web server or WordPress application.
84+
:::
85+
86+
:::info
87+
You can find more about the [supported options for the acquisition here](/log_processor/data_sources/appsec.md)
88+
:::
89+
90+
You can now restart CrowdSec:
91+
92+
```bash
93+
sudo systemctl restart crowdsec
94+
```
95+
96+
#### Testing the AppSec Component
97+
98+
##### Verify the AppSec Component is listening
99+
100+
To verify that the AppSec Component is running correctly, we can first check that the port `7422` is open and listening:
101+
102+
:::note
103+
If you have changed the port in the configuration file, replace `7422` with the new port number.
104+
:::
105+
106+
<Tabs
107+
defaultValue="netstat"
108+
groupId="listening-ports"
109+
values={[
110+
{label: 'Netstat', value: 'netstat'},
111+
{label: 'SS', value: 'ss'},
112+
]}>
113+
114+
<TabItem value="netstat">
115+
<CodeBlock className="language-bash">sudo netstat -tlpn | grep 7422</CodeBlock>
116+
</TabItem>
117+
118+
<TabItem value="ss">
119+
<CodeBlock className="language-bash">sudo ss -tlpn | grep 7422</CodeBlock>
120+
</TabItem>
121+
</Tabs>
122+
123+
<details>
124+
125+
<summary>Output example</summary>
126+
127+
```bash
128+
tcp 0 0 127.0.0.1:7422 0.0.0.0:* LISTEN 12345/crowdsec
129+
```
130+
131+
:::note
132+
The output may look differently depending on which command you used but as long as you see the port and the process `crowdsec`, it means the AppSec Component is running.
133+
:::
134+
135+
</details>
136+
137+
##### (Optional) Manually testing the AppSec Component with `curl`
138+
139+
<details>
140+
<summary>Expand for short guide</summary>
141+
142+
Before we proceed with configuring the Remediation Component, let's verify that all our current setups are functioning correctly.
143+
144+
1. Create a Remediation Component (Bouncer) API Key:
145+
146+
```bash
147+
sudo cscli bouncers add test_waf -k this_is_a_bad_password
148+
API key for 'test_waf':
149+
150+
this_is_a_bad_password
151+
152+
Please keep this key since you will not be able to retrieve it!
153+
```
154+
155+
2. Emit a legitimate request to the AppSec Component:
156+
157+
```bash
158+
curl -X POST localhost:7422/ -i -H 'x-crowdsec-appsec-uri: /test' -H 'x-crowdsec-appsec-ip: 192.168.1.1' -H 'x-crowdsec-appsec-host: foobar.com' -H 'x-crowdsec-appsec-verb: POST' -H 'x-crowdsec-appsec-api-key: this_is_a_bad_password'
159+
```
160+
161+
Which will give us an answer such as:
162+
163+
```bash
164+
HTTP/1.1 200 OK
165+
Date: Tue, 30 Jan 2024 15:43:50 GMT
166+
Content-Length: 36
167+
Content-Type: text/plain; charset=utf-8
168+
169+
{"action":"allow","http_status":200}
170+
```
171+
172+
3. Emit a malevolent request to the Appsec Component:
173+
174+
:::info
175+
We're trying to access a `.env` file, a [common way to get access to some credentials forgotten by a developer.](https://app.crowdsec.net/hub/author/crowdsecurity/appsec-rules/vpatch-env-access)
176+
:::
177+
178+
```bash
179+
curl -X POST localhost:7422/ -i -H 'x-crowdsec-appsec-uri: /.env' -H 'x-crowdsec-appsec-ip: 192.168.1.1' -H 'x-crowdsec-appsec-host: foobar.com' -H 'x-crowdsec-appsec-verb: POST' -H 'x-crowdsec-appsec-api-key: this_is_a_bad_password'
180+
181+
```
182+
183+
Our request is detected and blocked by the AppSec Component:
184+
185+
```bash
186+
HTTP/1.1 403 Forbidden
187+
Date: Tue, 30 Jan 2024 15:57:08 GMT
188+
Content-Length: 34
189+
Content-Type: text/plain; charset=utf-8
190+
191+
{"action":"ban","http_status":403}
192+
```
193+
194+
Let's now delete our test API Key:
195+
196+
```bash
197+
sudo cscli bouncers delete test_waf
198+
```
199+
200+
</details>
201+
202+
## Remediation Component Setup
203+
204+
Since our AppSec Component is active and listening, we can now configure the WordPress Remediation Component to forward requests to it.
205+
206+
The WordPress bouncer includes built-in AppSec support that can be enabled through the plugin's admin interface.
207+
208+
### Enable AppSec in WordPress Plugin
209+
210+
1. Log in to your WordPress admin panel
211+
2. Navigate to the CrowdSec plugin settings (`CrowdSec` in your admin menu)
212+
3. Go to the `Advanced` section
213+
4. Find the `AppSec component` configuration section
214+
5. Enable AppSec and configure the connection:
215+
216+
- **Enable AppSec**: Check this box to enable AppSec functionality
217+
- **URL**: Set to `http://127.0.0.1:7422` (or your custom AppSec Component address)
218+
- **Request timeout**: Default is 400 milliseconds (adjust as needed)
219+
- **Fallback to**: Choose `captcha` (recommended) for when AppSec calls fail
220+
- **Maximum body size**: Default is 1024 KB
221+
- **Body size exceeded action**: Choose `headers_only` (recommended)
222+
223+
224+
![appsec-config](/img/bouncer/wordpress/screenshots/config-appsec.png)
225+
226+
:::info
227+
AppSec functionality is only available when using API key authentication (not TLS certificates) in the WordPress plugin.
228+
:::
229+
230+
:::note
231+
The AppSec Component will only be consulted when the initial LAPI remediation returns a bypass decision.
232+
:::
233+
234+
## Testing the AppSec Component + Remediation Component
235+
236+
:::note
237+
We're assuming WordPress is running on your local machine. Please adjust your testing accordingly if this is not the case.
238+
:::
239+
240+
To test the AppSec functionality, you need to make a request that will go through the WordPress loading process. Try accessing a WordPress page with a malicious payload in the URL parameters or body.
241+
For example, we can try to post a request with a body that contains a malicious payload, known as a [Remote Code Execution (CVE-2022-22965)](https://app.crowdsec.net/hub/author/crowdsecurity/appsec-rules/vpatch-CVE-2022-22965) attempt.
242+
243+
```bash
244+
curl -X POST https://<your-wordpress-uri>/ -d "class.module.classLoader.resources." -o /dev/null -s -w "%{http_code}"
245+
```
246+
247+
248+
When the AppSec Component detects such a malicious request, you'll see that the response is a 403 (Forbidden) status code, indicating that the request was blocked.
249+
250+
If your test is not successful, please refer to the [Health check and troubleshoot guide](/u/getting_started/health_check/) for help.
251+
252+
253+
You can also look at the metrics from `cscli metrics show appsec` which will display:
254+
- the number of requests processed by the AppSec Component
255+
- Individual rule matches
256+
257+
<details>
258+
<summary>Example Output</summary>
259+
260+
261+
```bash title="sudo cscli metrics show appsec"
262+
Appsec Metrics:
263+
╭─────────────────┬───────────┬─────────╮
264+
│ Appsec Engine │ Processed │ Blocked │
265+
├─────────────────┼───────────┼─────────┤
266+
│ 127.0.0.1:7422/ │ 2 │ 1 │
267+
╰─────────────────┴───────────┴─────────╯
268+
269+
Appsec '127.0.0.1:7422/' Rules Metrics:
270+
╭─────────────────────────────────────┬───────────╮
271+
│ Rule ID │ Triggered │
272+
├─────────────────────────────────────┼───────────┤
273+
│ crowdsecurity/vpatch-CVE-2022-22965 │ 1 │
274+
╰─────────────────────────────────────┴───────────╯
275+
```
276+
277+
</details>
278+
279+
### Explanation
280+
281+
What happened in the test that we just did is:
282+
283+
1. We made a request with malicious payload to our WordPress site
284+
2. The WordPress bouncer plugin intercepted the request as part of the WordPress loading process
285+
3. The bouncer first checked with the local CrowdSec API for any existing decisions
286+
4. Since there was no existing ban decision, the bouncer forwarded the request to the AppSec Component at `http://127.0.0.1:7422`
287+
5. Our AppSec Component analyzed the request and matched it against the appropriate AppSec rules (here `crowdsecurity/vpatch-CVE-2022-22965` rule)
288+
6. The AppSec Component returned an HTTP 403 response to the WordPress bouncer, indicating that the request must be blocked
289+
7. The WordPress bouncer then presented the visitor with the configured ban page
290+
291+
## Integration with the console
292+
293+
If you haven't yet, follow the guide about [how to enroll your Security Engine in the console](/u/getting_started/post_installation/console).
294+
295+
Once done, all your alerts, including the ones generated by the AppSec Component, are going to appear in the console:
296+
297+
![appsec-console](/img/appsec_console.png)
298+
299+
## WordPress-Specific Considerations
300+
301+
### Understanding Plugin Limitations
302+
303+
The WordPress bouncer has some inherent limitations you should be aware of:
304+
305+
1. **WordPress Loading Process**: The plugin only protects requests that go through the WordPress core loading process. Direct access to PHP files outside of WordPress won't be protected.
306+
307+
2. **Static Files**: Requests for non-PHP files (like `.env`, `.sql`, or other static files) won't be processed by the plugin since they don't go through PHP.
308+
309+
3. **Auto Prepend File Mode**: For comprehensive protection, consider enabling [auto prepend file mode](/u/bouncers/wordpress#auto-prepend-file-mode) in the plugin settings to ensure all PHP scripts are protected.
310+
311+
312+
## Next steps
313+
314+
You are now running the AppSec Component on your WordPress site with CrowdSec Security Engine, congrats!
315+
316+
As the next steps, you can:
317+
- [Explore the hub](https://hub.crowdsec.net) to find more rules for your use case
318+
- Look at the [Rules syntax](/appsec/rules_syntax.md) and [creation process](/appsec/create_rules.md) to create your own and contribute

crowdsec-docs/sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,7 @@ const sidebarsConfig: SidebarConfig = {
711711
items: [
712712
{ type: "doc", id: "appsec/quickstart/nginxopenresty" },
713713
{ type: "doc", id: "appsec/quickstart/traefik" },
714+
{ type: "doc", id: "appsec/quickstart/wordpress" },
714715
],
715716
},
716717
{ type: "doc", id: "appsec/configuration" },

0 commit comments

Comments
 (0)