Enforcing Security in Web App Firewalls using Wazuh Active Response
Intro
Web Application Firewalls (WAF) filter, monitor, and block HTTP traffic to a web application. They use a combination of rule-based logic and signatures to detect and prevent attacks.
WAF deployment options include:
- Network-based WAF (generally a hardware-based appliance).
- Host-based WAF (fully integrated into an application’s software — Apache, NGINX or IIS).
- Cloud-based WAFs, such as Cloudflare.
In this entry we cover how to deploy a WAF using OpenSource technologies and how to enforce additional security leveraging Wazuh EDR and active response
Build your own WAF.
WAF Solution:
- OS: FreeBSD.
- Apache Web Server working as a reverse proxy.
- GeoIP integrated in Apache.
- Anti Malbots and Bad Referrers integrated in Apache.
- Apache ModSecurity Module: Security Engine.
- OWASP Core Rule Set (CRS): Rule Logic and signatures.
Why FreeBSD: High performance TCP/IP stack. Choose your own OS, if not familiar with BSD.
Apache + ModSecurity: Better performance than NGINX + ModSecurity. On top of that, Apache offers better logging capabilities too.
OWASP Core Rule Set (CRS): Used by most commercial WAFs:
- Azure WAF.
- AWS WAF.
- Cloudflare.
- Google Cloud Armor.
- Trustwave.
- F5 BIGIP WAF.
- Fortinet WAF.
- Citrix WAF.
- ……
GeoIP in Apache
Install GeoIP package and the module for Apache
pkg install geoipupdate
pkg install ap24-mod_maxminddb
Edit /usr/local/etc/GeoIP.conf and add account ID and License key:
# GeoIP.conf file for `geoipupdate` program, for versions >= 3.1.1.# Used to update GeoIP databases from https://www.maxmind.com.# For more information about this config file, visit the docs at# https://dev.maxmind.com/geoip/geoipupdate/.# `AccountID` is from your MaxMind account.AccountID account_id# `LicenseKey` is from your MaxMind accountLicenseKey key# `EditionIDs` is from your MaxMind account.EditionIDs GeoLite2-ASN GeoLite2-City GeoLite2-Country
Download GeoIP databases (execute command below):
/usr/local/bin/geoipupdate
After execution the GoIP databases will be downloaded into /usr/local/share/GeoIP:
ls -lrt /usr/local/share/GeoIP/total 62058-rw------- 1 root wheel 0 Dec 2 02:56 .geoipupdate.lock-rw-r--r-- 1 root wheel 7537328 Dec 2 02:56 GeoLite2-ASN.mmdb-rw-r--r-- 1 root wheel 73640335 Dec 2 02:56 GeoLite2-City.mmdb-rw-r--r-- 1 root wheel 6618745 Dec 2 02:56 GeoLite2-Country.mmdb
Edit /usr/local/etc/apache24/httpd.conf and add:
# Third party modules### maxminddb module addLoadModule maxminddb_module libexec/apache24//mod_maxminddb.so<IfModule maxminddb_module>MaxMindDBEnable OnMaxMindDBFile CITY_DB /usr/local/share/GeoIP/GeoLite2-City.mmdbMaxMindDBFile COUNTRY_DB /usr/local/share/GeoIP/GeoLite2-Country.mmdbMaxMindDBEnv MM_CONTINENT_CODE COUNTRY_DB/continent/codeMaxMindDBEnv MM_CONTINENT_NAME COUNTRY_DB/continent/names/enMaxMindDBEnv MM_COUNTRY_CODE COUNTRY_DB/country/iso_codeMaxMindDBEnv MM_COUNTRY_NAME COUNTRY_DB/country/names/en</IfModule>
To enable GeoIP, the module and blocking logic needs to be configured at vhost level. For Apache working as a reverse proxy, the settings need to be under the <Proxy> or <Location>sections.
GeoIP config for “deny by default, allow by exception”:
<Proxy *>SetEnvIf MM_COUNTRY_CODE COUNTRY_CODE_1 AllowedCountrySetEnvIf MM_COUNTRY_CODE COUNTRY_CODE_2 AllowedCountryorder deny,allowdeny from allallow from env=AllowedCountry</Proxy>
AntiBots / Bad Referrers
This GitHub repo includes instructions and required files to enable blocking “bad bots” and “bad referrers” from sending web requests.
Apache Reverse Proxy + ModSec + OWASP CRS
ModSec
Install ModSec module for Apache:
pkg install ap24-mod_security
(ModSec settings will be completed after downloading and enabling OWASP CRS)
OWASP Core Rule Set
OWASP CRS provides protection against many common attack categories.
SQL Injection, Cross Site Scripting, Local File Inclusion, etc.
The paranoia Level (1–4) determines the number of rules to load/apply.
Rules are applied to requests and responses (information leak prevention).
The anomaly score system is used to set a threshold for cumulated number of rule violations. Suspicious request above threshold will be blocked.
Downloading and enabling CRS in ModSec:
cd /usr/local/etc/modsecuritygit clone https://github.com/coreruleset/coreruleset.gitcd corerulesetcp crs-setup.conf.example /usr/local/etc/modsecurity/crs-setup.conf
Edit file /usr/local/etc/apache24/modules.d/280_mod_security.conf:
LoadModule unique_id_module libexec/apache24/mod_unique_id.soLoadModule security2_module libexec/apache24/mod_security2.soInclude /usr/local/etc/modsecurity/*.confInclude /usr/local/etc/modsecurity/coreruleset/rules/*.conf
Edit /usr/local/etc/modsecurity/modsecurity.conf and enable the rule engine; also recommended to increase PCRE limit (regex):
SecRuleEngine OnSecDebugLogLevel 0SecPcreMatchLimit 150000SecPcreMatchLimitRecursion 150000
A paranoia level of 2 is a good balance for security while trying to keep false positives to a minimum:
Edit /usr/local/etc/modsecurity/crs-setup.conf:
SecAction \"id:900000,\phase:1,\nolog,\pass,\t:none,\setvar:tx.paranoia_level=2
In the same file, modify the default action:
SecDefaultAction "phase:1,log,auditlog,deny"
SecDefaultAction "phase:2,log,auditlog,deny"
Rules 920350 (hostname in HTTP header is an IP address), 920280 and rule 920290 (Missing/Empty Host Header) and 920330 (Empty User-Agent Header) can be changed to a deny action (edit file /usr/local/etc/modsecurity/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf):
SecRule REQUEST_HEADERS:Host "@rx (?:^([\d.]+|\[[\da-f:]+\]|[\da-f:]+)(:[\d]+)?$)" \"id:920350,\phase:1,\deny,\t:none,\msg:'Host header is a numeric IP address',\logdata:'%{MATCHED_VAR}',\tag:'application-multi',\tag:'language-multi',\tag:'platform-multi',\tag:'attack-protocol',\tag:'paranoia-level/1',\tag:'OWASP_CRS',\tag:'capec/1000/210/272',\tag:'PCI/6.5.10',\ver:'OWASP_CRS/3.4.0-dev',\severity:'WARNING',\setvar:'tx.anomaly_score_pl1=+%{tx.warning_anomaly_score}'"
Wazuh Active Response + PF in action.
Kernel Filter for Blocked Requests.
How WAFs block HTTP requests:
Request not forwarded to the backend server.
HTTP Status = 403 — Forbidden sent to client (default).
Web scanners/crawlers/automation tools will keep sending requests.
Kill switch: Block traffic from repeated offenders using Packet Filters:
Inspect WAF activity via Apache Logs.
Translate WAF blocking event into a kernel packet filter rule.
Additionally, detect web scans via event correlation and apply filter rule as well.
Leveraging Wazuh’s active response we can activate BSD’s Packet Filter (pF) to dynamically block source IPs at kernel level for web requests blocked by ModSecurity.
The active response script “pf.sh” relies on a pF table named “ossec_fwtable”. We’ll enable pF on the WAF and enable this table.
Create the file “/etc/pf.conf” with the following configuration:
table <ossec_fwtable> persist #ossec_fwtableblock in on vtnet0 from <ossec_fwtable>
Where vtnet0 is the public interface on the WAF. Change as per your VM settings.
Enable pF as a service by adding the following lines to “/etc/rc.conf”:
pf_enable="YES"pf_rules="/etc/pf.conf"pflog_enable="YES"pflog_logfile="/var/log/pflog"
Start pF service:
service pf start
Wazuh Manager configuration to enable the active response:
<command><name>pf_block_ip</name><executable>pf.sh</executable><expect>srcip</expect><timeout_allowed>yes</timeout_allowed></command>----------------------------------------------<!-- WAF Active Response --><active-response><disabled>no</disabled><command>pf_block_ip</command><location>local</location><timeout>600</timeout><rules_id>30411</rules_id></active-response>
The AR is triggered by the rule with ID 30411 (“ModSecurity rejected a query”). After 10 mins, the source IP that got blocked will be removed from the pF table.
Adding “frequency” we can correlate several ModSec blocks from same IP before triggering the Active response.
With all the logic above applied, several events = “ModSecurity rejected a query” within the interval defined in the ruleset will trigger a correlation event of level 12 which, in turn, will activate the pF add in the WAF, blocking the SRC IP of the repeated offender:
Need Help?
The functionality discussed in this post, and so much more, are available via the SOCFortress platform. Let SOCFortress help you and your team keep your infrastructure secure.
Website: https://www.socfortress.co/
Platform Demo: https://www.socfortress.co/demo_access.html