ModSecurity is a powerful open-source Web Application Firewall (WAF) designed to enhance security and protect websites from various cyber threats. However, protection is not provided by the service alone. It needs a set of regulations in order to operate properly.
One well-known and reliable WAF ruleset is the OWASP CRS (Core Rule Set). OWASP, which stands for Open Web Application Security Project, is a globally recognized nonprofit organization that focuses on improving the security of web applications.
These regulations are adept at spotting possible attacks and averting them, serving as a strong defense against the majority of modern online threats.
The following documentation describes the process of implementing Nginx with ModSecurity and OWASP CRS on Debian-based servers, how to create a Whitelist for ModSecurity and the process of updating each component individually.
Table of contents:
- Installation
- 1. Installing NGINX and the required packages
- 2. Importing NGINX Source Code
- 3. Installing libmodsecurity3
- 4. Installing ModSecurity-nginx Connector
- 5. Installing ModSecurity 3 Dynamic Module
- 6. Enabling ModSecurity-nginx Connector
- 7. Installing OWASP CRS within ModSecurity
- 8. Verifying the Configuration and Rebooting Nginx
- 9. Setting up Logs Rotation for ModSecurity
- ModSecurity Whitelists
- Updating Nginx
- Updating ModSecurity
- Updating OWASP CRS
- Bibliography
Installation
Notes:
Before proceeding with the documentation, the system should be updated.
The following commands should be executed by the root user.
If Nginx is already installed on the server, it’s advised to remove it in order to make room for the newest version, which is available from a PPA (Personal Package Archive) that is kept up to date.
1. Installing NGINX and the required packages
The process begins with the installation of the following required packages.
apt install apt-transport-https ca-certificates curl git -y
Next, the following command should be run to import the Nginx PPA repository.
curl -sSL https://packages.sury.org/nginx-mainline/README.txt | bash -x
After the command has completed execution, the /etc/apt/sources.list.d/nginx.list
file should be edited to append the following line.
deb-src [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/nginx/ bookworm main
By default, Nginx source code is not bundled with the PPA installation. By adding this line, at a later stage, it will be possible to download Nginx source code, which is required to compile the ModSecurity module.
Next, the APT cache should be refreshed, and Nginx along with the remaining required packages should be installed.
apt update
apt upgrade -y
apt install nginx-core nginx-common nginx nginx-extras dpkg-dev gcc make build-essential autoconf automake libtool libcurl4-openssl-dev liblua5.3-dev libfuzzy-dev ssdeep gettext pkg-config libpcre3 libpcre3-dev libxml2 libxml2-dev libcurl4 libgeoip-dev libyajl-dev doxygen libpcre2-16-0 libpcre2-dev libpcre2-posix3 -y
If Nginx was previously installed on the server, during installation, a prompt asking to replace or keep the current /etc/nginx/nginx.conf
configuration file may appear. It’s advised to save the current configuration file by pressing n
in order to prevent any unplanned disruptions.
2. Importing NGINX Source Code
For ModSecurity and Nginx to be perfectly integrated, the ModSecurity dynamic module must be compiled using the Nginx source code. The following commands should be executed to create the directory that will store the Nginx source code and to download the code.
mkdir /usr/local/src/nginx
cd /usr/local/src/nginx
apt source nginx
To make sure the source code downloaded matches the current Nginx version installed on the server, the following commands should be executed.
ls
nginx -v
It is essential that both versions are the same in order to compile the ModSecurity module.
3. Installing libmodsecurity3
libmodsecurity3 serves as the foundation of ModSecurity’s powerful WAF. The source code for libmodsecurity3 should be downloaded from its GitHub repository using Git.
git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity /usr/local/src/ModSecurity/
cd /usr/local/src/ModSecurity/
Next, the following commands should be executed to initialize and update the Git submodules and to build/configure the ModSecurity environment.
git submodule init
git submodule update
./build.sh
./configure
An error message saying fatal: No names found, cannot describe anything
may appear during the configuration. This error message can be ignored.
Lastly, the following commands should be executed to compile the source code and to install it.
make -j $(nproc)
make install
4. Installing ModSecurity-nginx Connector
ModSecurity-nginx is the essential mediator between ModSecurity and the widely-used Nginx web server. The following command should be executed to clone the ModSecurity-nginx repository.
git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git /usr/local/src/ModSecurity-nginx/
Next, it is necessary to navigate to the Nginx source directory and execute the following commands to install the required dependencies for the ModSecurity-nginx connector.
cd /usr/local/src/nginx/nginx-1.*.*
apt build-dep nginx -y
apt install uuid-dev -y
To build the ModSecurity-nginx connector environment and generate the dynamic modules, the following commands must be executed.
./configure --with-compat --add-dynamic-module=/usr/local/src/ModSecurity-nginx
make modules
5. Installing ModSecurity 3 Dynamic Module
The final step of the setup process is to move the dynamic module generated by the previous steps into the /etc/nginx/modules/
directory.
mkdir -p /etc/nginx/modules/
cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
6. Enabling ModSecurity-nginx Connector
After the successful configuration of ModSecurity-nginx connector, the next step is to load it into Nginx. In order to do so, the file /etc/nginx/nginx.conf
must be edited. The following line should be located.
include /etc/nginx/modules-enabled/*.conf;
Below it, the following content must be added.
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
The http block
should be located, and the following directives should be inserted at the beginning of the block.
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/modsec-config.conf;
The directives above specify where the ModSecurity rules file is located and activate ModSecurity. Save and exit the file.
Next, it’s required to create a dedicated directory in order to hold the configuration files and rules.
mkdir /etc/nginx/modsec/
The example of ModSecurity configuration file should be copied into the newly created directory from the cloned ModSecurity Git repository.
cp /usr/local/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
Next, the /etc/nginx/modsec/modsecurity.conf
file should be edited in order to modify the ModSecurity rules.
By default, the ModSecurity rule engine operates in DetectionOnly mode, which logs malicious activity without blocking it. To change this behavior, the line starting with SecRuleEngine
should be located, and DetectionOnly
should be replaced with On
.
After that, the SecAuditLogParts
line should be identified.
SecAuditLogParts ABIJDEFHZ
The line should be adjusted as follows:.
SecAuditLogParts ABCEFHJKZ
Save and exit the file.
The next step is to create the /etc/nginx/modsec/modsec-config.conf
file. This file will contain the modsecurity.conf file along with additional rulesets like the OWASP CRS.
The following content must be copied into the file.
Include /etc/nginx/modsec/modsecurity.conf
Include /etc/nginx/modsec/coreruleset-4.15.0/crs-setup.conf
Include /etc/nginx/modsec/coreruleset-4.15.0/rules/*.conf
Lastly, replicate ModSecurity’s unicode.mapping file.
cp /usr/local/src/ModSecurity/unicode.mapping /etc/nginx/modsec/
7. Installing OWASP CRS within ModSecurity
The following commands should be executed in order to apply the OWASP CRS for ModSecurity to strengthen the security of the web server.
cd /etc/nginx/modsec
wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v4.15.0.tar.gz
tar -xvf v4.15.0.tar.gz
rm -r v4.15.0.tar.gz
cp /etc/nginx/modsec/coreruleset-4.15.0/crs-setup.conf.example /etc/nginx/modsec/coreruleset-4.15.0/crs-setup.conf
8. Verifying the Configuration and Rebooting Nginx
The following commands must be executed to verify the configuration and to enable/restart Nginx.
nginx -t
systemctl enable nginx
systemctl restart nginx
Expected output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
9. Setting up Logs Rotation for ModSecurity
In order to implement log rotation mechanism for ModSecurity the file /etc/logrotate.d/modsec
must be created and the following content added into it.
/var/log/modsec_audit.log
{
rotate 31
daily
missingok
compress
delaycompress
notifempty
}
Then, the following command needs to be executed to validate the logs rotation.
logrotate -d /etc/logrotate.d/modsec
ModSecurity Whitelists
In ModSecurity, a whitelist (also known as an allowlist) is a list of approved exceptions. These exceptions are normally defined when false positives are being generated by the rulesets, affecting the expected behavior of the website.
In order to create a whitelist, the Nginx and ModSecurity logs should be analyzed to identify the rule IDs responsible for false positives and the corresponding affected request paths. Then, a new file with the .conf
extension should be created in the /etc/nginx/modsec/
directory.
Inside the file, a new custom rule with an ID greater than 1000000 should be defined. The rule will instruct ModSecurity to disable specific rules that generate false positives for the paths identified in the analysis.
An example of this can be seen in the following code.
SecRule REQUEST_URI "@contains /wp-admin/" \
"id:1000200,phase:1,nolog,pass,\
ctl:ruleRemoveById=920350,\
ctl:ruleRemoveById=920280"
Once the whitelist has been created, it can be implemented for the entire web server or only for a specific vhost (Virtual Host).
To implement the whitelist for the entire web server, the file /etc/nginx/nginx.conf
must be edited and the following line located.
modsecurity_rules_file /etc/nginx/modsec/modsec-config.conf;
Below it, the following code should be added, ensuring that the file name is updated accordingly.
modsecurity_rules_file /etc/nginx/modsec/<filename>.conf;
To implement the whitelist for a specific vhost, the previous code should be added inside the corresponding server block.
Lastly, restart Nginx to load the whitelist.
systemctl restart nginx.service
Updating Nginx
In order to implement ModSecurity with Nginx, it’s necessary to compile the ModSecurity-nginx Connector for the version of Nginx installed on the system. When updates are available for Nginx, it is necessary to recompile the Connector afther the upgrade.
To ensure that no errors are triggered during the update, the /etc/nginx/nginx.conf
file must be edited, and all lines referencing modsecurity
should be commented out.
The service should be restarted, and the system update should be carried out. Once the update is complete, the following commands should be executed.
rm -r /usr/local/src/nginx
rm -r /usr/local/src/ModSecurity-nginx/
Next, steps 2, 4, 5 and 6 should be executed to recompile the ModSecurity-nginx Connector.
Finally, all lines referencing modsecurity
in the /etc/nginx/nginx.conf
file should be uncommented, and the Nginx service should be restarted.
systemctl restart nginx.service
Updating ModSecurity
In order to update ModSecurity, the following commands must be executed. The process should begin by removing the currently installed version of libmodsecurity3 from the system.
rm -r /usr/local/src/ModSecurity/
Then, step 3 should be re-executed to install the updated ModSecurity environment. Next, the following command should be executed to copy the example ModSecurity configuration file into the /etc/nginx/modsec/
directory.
cp /usr/local/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
The ModSecurity unicode.mapping file should be replicated.
cp /usr/local/src/ModSecurity/unicode.mapping /etc/nginx/modsec/
Finally, Nginx should be restarted.
systemctl restart nginx.service
Updating OWASP CRS
The official OWASP CRS GitHub repository 1 should be consulted to check whether a new release is available. If a new release is available, the following commands should be executed to delete the current ruleset used by ModSecurity on the system.
cd /etc/nginx/modsec/
rm -r coreruleset-*
Step 7 should be re-executed to download the new release. The commands must be updated to reflect the new release version.
Next, the /etc/nginx/modsec/modsec-config.conf
file should be edited to update the release version accordingly.
Include /etc/nginx/modsec/coreruleset-x.y.z/crs-setup.conf
Include /etc/nginx/modsec/coreruleset-x.y.z/rules/*.conf
Finally, Nginx must be restarted in order to load the updated ruleset.
systemctl restart nginx.service