ModSecurity for NGINX, also known as ModSecurity-nginx, is a web application firewall module for the NGINX web server. It provides similar functionality to the original ModSecurity module for Apache, but is designed to work specifically with the NGINX web server.
Like the Apache module, ModSecurity-nginx analyzes incoming HTTP traffic and applies a set of predefined security rules to identify and block malicious or suspicious requests. It can also be configured to log request data and perform various other actions, such as blocking specific IP addresses or user agents.
ModSecurity is available as a package in the Ubuntu repositories, so you can install it using the package manager.
To install ModSecurity on Ubuntu 18.04.6 LTS, you can follow these steps:
Update the package index and upgrade the system packages:
sudo apt-get update
sudo apt-get upgrade
If you do not have NGINX Web Server installed on your server already, install NGINX using the following command. If you have NGINX installed already, you can ignore this step.
sudo apt install nginx
The next step is to clone mode ModSecurity from github
. It’s a good habit to clone installation files to the /opt
folder so let’s get ahead and run the command:
cd /opt
Once you are in the /opt
folder, proceed by cloning https://github.com/SpiderLabs/ModSecurity from github
.
git clone https://github.com/SpiderLabs/ModSecurity
Proceed by navigating inside the newly created folder.
cd ModSecurity
Once you are inside the folder, you have to ensure that all the submodules are inside are initialized and updated. You can do this by running the commands below:
git submodule init && git submodule update
First, you need to install the following dependencies for the build process.
sudo apt-get install libtool m4 automake
Once done, you can now start the build process
using the command below:
sh build.sh
Install the following dependencies before proceeding.
apt-get install liblmdb-dev libxml2-dev liblua5.3-dev libcurl4-openssl-dev libpcre3 libpcre3-dev
Once done, you should run the sh configure
command and this will show you if you have all the tools and dependencies installed.
sh configure
After everything you can now run the make
command.
make
After that, this is the only time you can now really install by running the commands below:
make install
Congratulations! ModSecurity is now setup and installed on your server.
Once again, let’s clone installation files to the /opt
folder so let’s get ahead and run the command:
cd /opt
Once you are in the /opt
folder, proceed by cloning https://github.com/SpiderLabs/ModSecurity-nginx from github
.
git clone https://github.com/SpiderLabs/ModSecurity-nginx
Proceed by navigating inside the newly created folder.
cd ModSecurity-nginx
Before proceeding, we all need to understand that ModSecurity works only on certain number of versions from NGINX. Not having the proper version may result into a failure of installation.
Let’s proceed by checking the version of NGINX currently installed.
nginx -v
You will see a message similar to this:
nginx version: nginx/1.14.0 (Ubuntu)
This means that the current version of NGINX installed on our server is 1.14.0
. You need to make sure that you take this down.
This means that you have to download NGINX installation similar to this version. You can proceed by navigating to the /opt
folder once again and running the command below:
cd /opt && wget https://nginx.org/download/nginx-1.14.0.tar.gz
Please remember to replace 1.14.0
with the version of NGINX you are using when you’ve execute nginx -v
.
To extract the file, you must run
tar -xzvf nginx-1.14.0.tar.gz
Let’s proceed inside that directory.
cd nginx-1.14.0
The next thing to do is to configure ModeSecurity to connect to our NGINX. In order to that, we need get specific configure arguments which will vary depending on your environment.
Install the following dependencies before proceeding
sudo apt-get install libssl-dev zlib1g-dev libxslt-dev libgd-dev libgeoip-dev
You can do that by running the command below:
nginx -V
If you are doing everything right. You will get the following output:
nginx version: nginx/1.14.0 (Ubuntu)
built with OpenSSL 1.1.1 11 Sep 2018
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-YlUNvj/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module
What you need do is to copy the information that comes after the configure arguments
. You can can check the needed information below. Please take note that this will vary depending on the environment.
--with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-YlUNvj/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module
Make sure that you are still in the folder /opt/nginx-1.14.0
. You can now proceed on running the code.
sh configure <configure-argument> --add-dynamic-module="../ModSecurity-nginx"
by replacing the <configure-argument>
it will become:
sh configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-YlUNvj/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module="../ModSecurity-nginx"
If you encounter this and other errors:
configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl=<path> option.
Once done, you must run sh configure with the other arguments above again. You should get the following message to know that it worked:
Configuration summary
+ using threads
+ using system PCRE library
+ using system OpenSSL library
+ using system zlib library
nginx path prefix: "/usr/share/nginx"
nginx binary file: "/usr/share/nginx/sbin/nginx"
nginx modules path: "/usr/lib/nginx/modules"
nginx configuration prefix: "/etc/nginx"
nginx configuration file: "/etc/nginx/nginx.conf"
nginx pid file: "/run/nginx.pid"
nginx error log file: "/var/log/nginx/error.log"
nginx http access log file: "/var/log/nginx/access.log"
nginx http client request body temporary files: "/var/lib/nginx/body"
nginx http proxy temporary files: "/var/lib/nginx/proxy"
nginx http fastcgi temporary files: "/var/lib/nginx/fastcgi"
nginx http uwsgi temporary files: "/var/lib/nginx/uwsgi"
nginx http scgi temporary files: "/var/lib/nginx/scgi"
If you get the correct message above without any error. It’s to make the modules. You c an do this by running the command below:
make modules
This will create a module that will facilitate the connection between MODSECURITY and NGINX.
You can view the modules by running ls objs
. If you are in the right track, you will see the following output:
root@server-admin:/opt/nginx-1.14.0# ls objs
addon ngx_http_image_filter_module_modules.o ngx_mail_module_modules.o
autoconf.err ngx_http_image_filter_module.so ngx_mail_module.so
Makefile ngx_http_modsecurity_module_modules.c ngx_modules.c
ngx_auto_config.h ngx_http_modsecurity_module_modules.o ngx_stream_module_modules.c
ngx_auto_headers.h ngx_http_modsecurity_module.so ngx_stream_module_modules.o
ngx_http_geoip_module_modules.c ngx_http_xslt_filter_module_modules.c ngx_stream_module.so
ngx_http_geoip_module_modules.o ngx_http_xslt_filter_module_modules.o src
ngx_http_geoip_module.so ngx_http_xslt_filter_module.so
ngx_http_image_filter_module_modules.c ngx_mail_module_modules.c
Make sure you are on the correct folder path before proceeding:
cd /opt/nginx-1.14.0
Create a folder inside your nginx called _modules
.
mkdir /etc/nginx/_modules
Copy ngx_https_modsecurity_module.so
to the newly created folder.
cp objs/ngx_http_modsecurity_module.so /etc/nginx/_modules
The next thing to do is to modify your nginx.conf
file located on /etc/nginx/nginx.conf
.
nano /etc/nginx/nginx.conf
At the beginning you can see the following:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
All you have to to is insert load_module /etc/nginx/_modules/ngx_http_modsecurity_module.so
after include /etc/nginx/modules-enabled/*.conf;
The settings will look like this:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
load_module /etc/nginx/_modules/ngx_http_modsecurity_module.so;
events {
worker_connections 768;
# multi_accept on;
}
With this, ModSecurity for NGINX has been loaded.
Let’s go back to our /opt
folder to setup a ruleset. Once you are on the folder we will clone another git from https://github.com/coreruleset/coreruleset.
cd /opt
You can do it by running the code below on our /opt
folder.
git clone https://github.com/coreruleset/coreruleset modsecurity-crs
Get inside the folder by executing:
cd modsecurity-crs
Inside the folder you can the following folder:
CHANGES.md CONTRIBUTORS.md docs KNOWN_BUGS.md plugins regex-assembly SECURITY.md tests
CONTRIBUTING.md crs-setup.conf.example INSTALL LICENSE README.md rules SPONSORS.md util
You will have to rename crs-setup.conf.example
to crs-setup.conf
. You can do it by executing the following commands:
mv crs-setup.conf.example crs-setup.conf
We can now modify the rules. First we will modify the request exclusion rules.
mv rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
This will rename our request exclusion rules
.
The next thing to do is to move it to the user local directory. First thing’s first, let’s go back into our /opt
.
mv /opt/modsecurity-crs /usr/local
The now have the following folders in your local
directory.
/usr/local/modsecurity
/usr/local/modsecurity-crs
Let’s create the folder for ModSecurity Configuration by executing the following commands:
mkdir -p /etc/nginx/modsec
The files that we need for the ModSecurity Configuration are unicode.mapping
and mv modsecurity.conf-recommended
. We will be replace mv modsecurity.conf-recommended
to modsecurity.conf
.
cp /opt/ModSecurity/unicode.mapping /etc/nginx/modsec/
mv /opt/ModSecurity/modsecurity.conf-recommended /opt/ModSecurity/modsecurity.conf
cp /opt/ModSecurity/modsecurity.conf /etc/nginx/modsec/
Your /etc/nginx/modsec
will not look like this if you use ls
.
modsecurity.conf unicode.mapping
Now that we are done with the setup of the files. What you need to understand is that you can configure ModSecurity.
You can see the configuration in /etc/nginx/modsec/modsecurity.conf
which is the file that you have created before.
nano /etc/nginx/modsec/modsecurity.conf
The settings thing that you need to change is:
SecRuleEngine DetectionOnly
You have to set this to On
therefore it will look like this:
SecRuleEngine On
This enables the security instead of just detecting it.
In addition to ModSecurity File we now need to create a main configuration file. Inside the /etc/nginx/modsec/
create a main configuration file. /etc/nginx/modsec/main.conf
.
nano /etc/nginx/modsec/main.conf
Inside this the main configuration file. Add the following:
Include /etc/nginx/modsec/modsecurity.conf
Include /usr/local/modsecurity-crs/crs-setup.conf
Include /usr/local/modsecurity-crs/rules/*.conf
You directory should look like this once your run ls -alps
4 drwxr-xr-x 2 root root 4096 Mar 17 11:28 ./
4 drwxr-xr-x 9 root root 4096 Mar 16 23:11 ../
4 -rw-r--r-- 1 root root 141 Mar 17 11:28 main.conf
12 -rw-r--r-- 1 root root 11187 Mar 17 11:22 modsecurity.conf
52 -rw-r--r-- 1 root root 53146 Mar 16 23:11 unicode.mapping
We are not done setting up all the files that we need.
In order to apply ModSecurity to your website, you have to edit the sites-available
configuration of your website.
For example we are going to modify our /etc/nginx/sites-available/default
.
server {
listen 50 default_server;
listen [::]:50 default_server;
root /var/www/test_bets;
index index.html index.htm index.nginx-debian.html index.php;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
In between, the root /var/www/test_bets
and index index.html index.htm
we must add the following:
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
Therefore it will look like this
server {
listen 50 default_server;
listen [::]:50 default_server;
root /var/www/test_bets;
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
index index.html index.htm index.nginx-debian.html index.php;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
The last thing to do is to restart nginx
and check if everything is working out correctly.
systemctl reload nginx
systemctl restart nginx
These are list of additional fixes that needs to be done based on experience.
sh
sudo nano +435 /usr/local/modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
sudo nano +77 /usr/local/modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
Note: Comment the entire rules on line 435
If you didn’t see any error then everything is working out correctly.
You can simple test if it’s working, using a simple CURL command.
curl http://<ip-address>/index.php?exec=/bin/bash
If it’s working correctly, you should get:
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.0 (Ubuntu)</center>
</body>
</html>
This means that your malicious script was blocked by ModSecurity.
The module is configured to protect web applications from various attacks. ModSecurity supports flexible rule engine to perform both simple and complex operations. It comes with a Core Rule Set (CRS) which has various rules for: