CrowdSec WAF QuickStart for Nginx/OpenResty
Objectives
The goal of this quickstart is to set up the AppSec Component to safeguard web applications running on Nginx or OpenResty.
We'll deploy a set of rules designed to block well-known attacks and currently exploited vulnerabilities.
Additionally, we'll show how to monitor these alerts through the console.
Pre-requisites
-
If you're new to the AppSec Component or Web Application Firewalls, start with the Introduction for a better understanding.
-
It's assumed that you have already installed:
- CrowdSec Security Engine: for installation, refer to the QuickStart guide. The AppSec Component, which analyzes HTTP requests, is included within the security engine as a Acquisition.
- One of the supported web servers for this guide:
- Nginx Remediation Component: installation instructions are available in the QuickStart guide.
- OpenResty Remediation Component: installation instructions are available in the QuickStart guide.
This component intercepts HTTP requests at the webserver or reverse-proxy level and forwards them to the AppSec Component for analysis and action.
The reason we provide Nginx and OpenResty in a single guide is that OpenResty is a web server based on Nginx just the configuration paths are different
AppSec Component Setup
Collection installation
To begin setting up the AppSec Component, the initial step is to install a relevant set of rules.
We will utilize the crowdsecurity/appsec-virtual-patching
collection, which offers a wide range of rules aimed at identifying and preventing the exploitation of known vulnerabilities.
This collection is regularly updated to include protection against newly discovered vulnerabilities. Upon installation, it receives automatic daily updates to ensure your protection is always current.
Furthermore we also install the crowdsecurity/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).
On the machine where the Security Engine is installed, just execute the following command:
You can always view the content of a collection on the hub
sudo cscli collections install crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules
Executing this command will install the following items:
- The AppSec Rules contain the definition of malevolent requests to be matched and stopped
- The AppSec Configuration links together a set of rules to provide a coherent set
- The CrowdSec Parser and CrowdSec Scenario(s) bans for a longer duration repeating offenders
Setup the Acquisition
Having installed the required components, it's time to configure the CrowdSec Acquisition to expose the Application Security Component to our web server. This configuration allows our Nginx/OpenResty server to send requests to the AppSec Component for evaluation and decision-making.
Steps:
- Create the
/etc/crowdsec/acquis.d/
directory (if it doesn't exist on your machine)
mkdir -p /etc/crowdsec/acquis.d/
- Create a file
/etc/crowdsec/acquis.d/appsec.yaml
with the following content:
appsec_config: crowdsecurity/appsec-default
labels:
type: appsec
listen_addr: 127.0.0.1:7422
source: appsec
The two important directives in this configuration file are:
appsec_config
is the name of the AppSec Configuration that was included in the Collection we just installed.- the
listen_addr
is the IP and port the AppSec Component will listen to.
We do not recommend exposing the AppSec Component to the internet. It should only be accessible from the web server or reverse proxy.
You can find more about the supported options for the acquisition here
You can now restart CrowdSec:
sudo systemctl restart crowdsec
Testing the AppSec Component
Verify the AppSec Component is listening
To verify that the AppSec Component is running correctly, we can first check that the port 7422
is open and listening:
If you have changed the port in the configuration file, replace 7422
with the new port number.
- Netstat
- SS
sudo netstat -tlpn | grep 7422
sudo ss -tlpn | grep 7422
Output example
tcp 0 0 127.0.0.1:7422 0.0.0.0:* LISTEN 12345/crowdsec
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.
(Optional) Manually testing the AppSec Component with curl
Expand for short guide
Before we proceed with configuring the Remediation Component, let's verify that all our current setups are functioning correctly.
- Create a Remediation Component (Bouncer) API Key:
sudo cscli bouncers add test_waf -k this_is_a_bad_password
API key for 'test_waf':
this_is_a_bad_password
Please keep this key since you will not be able to retrieve it!
- Emit a legitimate request to the AppSec Component:
curl -X POST localhost:7422/ -i -H 'x-crowdsec-appsec-uri: /test' -H 'x-crowdsec-appsec-ip: 42.42.42.42' -H 'x-crowdsec-appsec-host: foobar.com' -H 'x-crowdsec-appsec-verb: POST' -H 'x-crowdsec-appsec-api-key: this_is_a_bad_password'
Which will give us an answer such as:
HTTP/1.1 200 OK
Date: Tue, 30 Jan 2024 15:43:50 GMT
Content-Length: 36
Content-Type: text/plain; charset=utf-8
{"action":"allow","http_status":200}
- Emit a malevolent request to the Appsec Component:
We're trying to access a .env
file, a common way to get access to some credentials forgotten by a developer.
curl -X POST localhost:7422/ -i -H 'x-crowdsec-appsec-uri: /.env' -H 'x-crowdsec-appsec-ip: 42.42.42.42' -H 'x-crowdsec-appsec-host: foobar.com' -H 'x-crowdsec-appsec-verb: POST' -H 'x-crowdsec-appsec-api-key: this_is_a_bad_password'
Our request is detected and blocked by the AppSec Component:
HTTP/1.1 403 Forbidden
Date: Tue, 30 Jan 2024 15:57:08 GMT
Content-Length: 34
Content-Type: text/plain; charset=utf-8
{"action":"ban","http_status":403}
Let's now delete our test API Key:
sudo cscli bouncers delete test_waf
Remediation Component Setup
Since our AppSec Component is active and listening, we can now configure the Remediation Component to forward requests to it.
To setup forwarding of requests in the remediation component, we'll modify its configuration file and append the following line:
Nginx
:/etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf
OpenResty
:/etc/crowdsec/bouncers/crowdsec-openresty-bouncer.conf
APPSEC_URL=http://127.0.0.1:7422
This instructs the remediation component to communicate with the AppSec Component at http://127.0.0.1:7422
.
Once configured, all incoming HTTP requests will be sent there for analysis. The snippet above assumes that the AppSec Component is running on the same machine.
We can now restart the service:
sudo systemctl restart nginx
Testing the AppSec Component + Remediation Component
We're assuming the web server is installed on the same machine and is listening on port 80. Please adjust your testing accordingly if this is not the case.
if you try to access http://localhost/.env
from a browser, your request will be blocked, resulting in the display of the following HTML page:
We can also look at the metrics from cscli metrics show appsec
it will display:
- the number of requests processed by the AppSec Component
- Individual rule matches
Example Output
Appsec Metrics:
╭─────────────────┬───────────┬─────────╮
│ Appsec Engine │ Processed │ Blocked │
├─────────────────┼───────────┼─────────┤
│ 127.0.0.1:7422/ │ 2 │ 1 │
╰─────────────────┴───────────┴─────────╯
Appsec '127.0.0.1:7422/' Rules Metrics:
╭──────────── ─────────────────────┬───────────╮
│ Rule ID │ Triggered │
├─────────────────────────────────┼───────────┤
│ crowdsecurity/vpatch-env-access │ 1 │
╰─────────────────────────────────┴───────────╯
Explanation
What happened in the test that we just did is:
- We did a request (
localhost/.env
) to our local webserver - Thanks to the Remediation Component configuration, forwarded the request to
http://127.0.0.1:7422
- Our AppSec Component, listening on
http://127.0.0.1:7422
analyzed the request - The request matches the AppSec rule to detect .env access
- The AppSec Component thus answered with HTTP 403 to the Remediation Component, indicating that the request must be blocked
- The web server then presented us with the default "request blocked" page.
Integration with the console
If you haven't yet, follow the guide about how to enroll your Security Engine in the console.
Once done, all your alerts, including the ones generated by the AppSec Component, are going to appear in the console:
Next steps
You are now running the AppSec Component on your Crowdsec Security Engine, congrats!
As the next steps, you can:
- Explore the hub to find more rules for your use case
- Look at the Rules syntax and creation process to create your own and contribute
- Take a look at the benchmarks