How to Secure Nginx with Naxsi Firewall on Ubuntu 18.04 VPS

Last updated: November 10th 2022

Introduction

Nginx is one of the most popular and high-performance web servers in the world. So it is very important part of any system administrator to increase the security of the Nginx server. Naxsi "Nginx Anti XSS & SQL Injection" is a free, open-source and high-performance web application firewall that can be used to protect your webserver against different types of attacks like SQL Injections and Cross-Site Scripting. Naxsi works by detecting unexpected characters in the HTTP GET and POST requests.

In this tutorial, we will show you how to install and configure Naxsi firewall to protect the Nginx server on Ubuntu 18.04 server.

Please note: Doing these actions will temporarily bring down your server. Do not do this on a live site. If you want to add Naxsi to a live server, create a new server from a snapshot and test this out - then migrate your changes back to your live server once you've verified everything is working.

Prerequisites

Getting Started

Before starting, it is recommended to update your system's package to the latest version. You can update them with the following commands:

apt-get update -y
apt-get upgrade -y

 

Once all the packages are updated, restart your server to apply all the configuration changes.

Next, you will need to install all the dependencies required to install Naxsi. You can install all of them with the following command:

apt-get install zlib1g zlib1g-dev build-essential bzip2 unzip libpcre3-dev libssl-dev libgeoip-dev wget unzip libxslt-dev libgd-dev -y

Once all the dependencies are installed, you can proceed to the next step.

Compile Nginx with Naxsi Support

By default, Nginx is pre-installed in Webdock Ubuntu 18.04 instance. But, Naxsi is a third-party Nginx module that does not comes with Nginx package.
So, you will need to download Nginx and Naxsi source, and compile Nginx with Naxsi support.

First, check the installed version of Nginx on your Webdock instance with the following command:

nginx -v

Output:

nginx version: nginx/1.17.0


Once you get the Nginx version, go to the Nginx official website and download the same Nginx version with the following command:

wget http://nginx.org/download/nginx-1.17.0.tar.gz

Next, download the latest version of Naxsi with the following command:

wget https://github.com/nbs-system/naxsi/archive/master.zip

Next, extract the downloaded source file with the following commands:

tar -xvzf nginx-1.17.0.tar.gz
unzip master.zip

 

Before recompiling Nginx, you will also need to find all the installed Nginx modules in the system.
You can list them with the following command:

nginx -V

You should see the output similar to the following:

nginx version: nginx/1.17.0
built with OpenSSL 1.1.1b 26 Feb 2019 (running with OpenSSL 1.1.1c 28 May 2019)
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-RFWPEB/nginx-1.17.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-stream_ssl_preread_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-RFWPEB/nginx-1.17.0/debian/modules/http-auth-pam --add-dynamic-module=/build/nginx-RFWPEB/nginx-1.17.0/debian/modules/http-dav-ext --add-dynamic-module=/build/nginx-RFWPEB/nginx-1.17.0/debian/modules/http-echo --add-dynamic-module=/build/nginx-RFWPEB/nginx-1.17.0/debian/modules/http-upstream-fair –add-dynamic-module=/build/nginx-RFWPEB/nginx-1.17.0/debian/modules/http-subs-filter

Next, stop the running Nginx service with the following command:

systemctl stop nginx

Next, remove all dynamic modules, add new arguement –add-module=/root/naxsi-master/naxsi_src/ and --sbin-path=/usr/sbin/nginx and add ./configure at the beginning of configure arguements.

After making all the changes, copy these commands and run on the terminal as shown below:

cd nginx-1.17.0
./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-RFWPEB/nginx-1.17.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' --add-module=../naxsi-master/naxsi_src/ --sbin-path=/usr/sbin/nginx --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-stream_ssl_preread_module --with-mail=dynamic --with-mail_ssl_module

 

Next, run the make command to run a series of tasks defined in the Makefile:

make

Next, run the make install command to copy all the configuration files to their correct location:

make install

Once the above command runs successfully that means Nginx has been recompiled with Naxsi support.

Next, start the Nginx service with the following command:

systemctl start nginx

You can verify the Nginx service status with the following command:

systemctl status nginx

If everything goes fine, you should get the following output:

● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2019-08-16 09:17:06 UTC; 7s ago
Docs: man:nginx(8)
Process: 16521 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 16520 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 16522 (nginx)
Tasks: 13 (limit: 4915)
CGroup: /system.slice/nginx.service
├─16522 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
├─16523 nginx: worker process
├─16524 nginx: worker process
├─16525 nginx: worker process
├─16526 nginx: worker process
├─16527 nginx: worker process
├─16528 nginx: worker process
├─16529 nginx: worker process
├─16530 nginx: worker process
├─16531 nginx: worker process
├─16532 nginx: worker process
├─16533 nginx: worker process
└─16534 nginx: worker process

Aug 16 09:17:06 ubuntu systemd[1]: Starting A high performance web server and a reverse proxy server...
Aug 16 09:17:06 ubuntu systemd[1]: Started A high performance web server and a reverse proxy server.

Configure Naxsi

Naxsi comes with a set of core rules that can be used to determine how requests are blocked from the server. So, you will need to copy Naxsi core rules to the Nginx configuration directory. You can copy them from Naxsi source directory with the following command:

cp -r /root/naxsi-master/naxsi_config/naxsi_core.rules /etc/nginx/

Next, you will need to enable Naxsi rules and define different types of attacks that can be blocked by Naxsi. You can do it by creating naxsi.rules file:

nano /etc/nginx/naxsi.rules

Add the following lines:

SecRulesEnabled;
DeniedUrl "/error.html";

## Check Naxsi rules
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;

Save and close the file when you are finished.

Next, you will need to create an error.html file to redirected blocked requests to error.html file. Place this in your web root as defined in your nginx configuration, on Webdock this is typically /var/www/html

nano /var/www/html/error.html

Make sure this file is owned by a user and group which belongs to your web server, typically www-data, or you will get a 403 forbidden response instead of the browser showing the block message - to change ownership of the file, execute:

chown www-data:www-data /var/www/html/error.html

Add the following lines:

<html>
<head>
<title>Blocked By NAXSI</title>
</head>
<body>
<div style="text-align: center">
<h1>Malicious Request</h1>
<hr>
<p>This Request Has Been Blocked By NAXSI.</p>
</div>
</body>
</html>

Save and close the file. Then, configure Nginx server to include Naxsi rules by editing nginx.conf file:

nano /etc/nginx/nginx.conf

Add the following lines within http {} section:

include /etc/nginx/naxsi_core.rules;

Save and close the file.

Next, create or edit an existing Nginx virtual host file and include naxsi.rules. You will need to include naxsi.rules file in each virtual host that you want to enable Naxsi.

nano /etc/nginx/sites-available/webdock.conf

Add highlighted line to your location / {} block:

server {
listen 80;

root /usr/share/nginx/html;
index index.html index.htm;

# Make site accessible from http://localhost/
server_name 136.243.240.38;

location / {
include /etc/nginx/naxsi.rules;

try_files $uri $uri/ =404;

}

}

Save and close the file. Then, check Nginx for any syntax error with the following command:

nginx -t

If everything goes fine, you should get the following output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Finally, restart Nginx service to apply all the configuration changes:

systemctl restart nginx


Test Naxsi Firewall

Naxsi firewall is now installed and configured, it's time to test it against SQLi and XSS attack.

To test Naxsi against XSS attack, open your web browser from the remote system and type the URL http://136.243.240.38/q?="><script>alert(1)</script> . As per the Naxsi rules which you have configured earlier, you should be redirected to the error.html page with the following message:

naxsi1.png

You can also verify this by checking Nginx log as shown below:

tail -f /var/log/nginx/error.log

You should see that XSS request from the remote host has been blocked by Naxsi firewall:

2019/08/15 03:03:13 [error] 12773#0: *6 NAXSI_FMT: ip=27.61.137.35&server=136.243.240.38&uri=/&vers=0.56&total_processed=4&total_blocked=3&config=block&cscore0=$SQL&score0=8&cscore1=$XSS&score1=8&zone0=ARGS&id0=1001&var_name0=q, client: 27.61.137.35, server: localhost, request: "GET /?q="><script>alert(1)</script> HTTP/1.1", host: "136.243.240.38"

To test Naxsi against SQLi attack, open your web browser from the remote system and type the URL http://136.243.240.38/?q=1" or "1"="1". You should get the same message as shown in the following page:

naxsi1.png

You can also check the Nginx server log again with the following command:

tail -f /var/log/nginx/error.log

You should get the same message as shown below:

2019/08/15 02:59:52 [error] 12773#0: *1 NAXSI_FMT: ip=27.61.137.35&server=136.243.240.38&uri=/&vers=0.56&total_processed=1&total_blocked=1&config=block&cscore0=$SQL&score0=40&cscore1=$XSS&score1=40&zone0=ARGS&id0=1001&var_name0=q, client: 27.61.137.35, server: localhost, request: "GET /?q=1%22%20or%20%221%22=%221%22 HTTP/1.1", host: "136.243.240.38"

 

Congratulations! you have successfully setup Naxsi firewall to protect Nginx server against malicious attacks. Your Nginx webserver is now secured from XSS and SQL injection attack. For more information, you can visit the Naxsi official documentation at Naxsi Doc.

Related articles