Compiling Modules for NGINX

An example with ModSecurity and Cookie-Flag modules.

Maxime Durand
6 min readFeb 9, 2019

There are many modules for NGINX. You will also find a list with certified modules on the official website. With NGINX Plus it is very simple to enable or add some modules. In the NGINX Open Source version it will be necessary to compile and link them to your server. This article describes the different operations to add your modules to NGINX.

When we are installing a new server we should all have as a priority: it’s security. As we see today, the most common problems we have on the web are often related to security.

Even if you can never be completely safe, keeping this priority in mind is already a good start.

After spending a some time on my NGINX configuration and trying to get as much A+ as possible on Mozilla Observatory, I wanted to deepen the security on my server. I have seen that one of the first good practices is to deploy a Web Application Firewall. That’s how I discovered ModSecurity and the NGINX modules.

The WAF will protect the highest layer of the OSI model: the application layer.

By the way, we will also deploy the Cookie-Flag module. It is a NGINX module for adding cookie flags that I find really interesting. In my Mozilla Observatory’s A+ quest, I realized that to get these scores, I would have to force parameters that should be done in the website code. But sometimes, if we only deploy them, we don’t have access to these parameters. This why, I wanted to activate some cookies settings directly from NGINX, such as Secure or HttpOnly which are part of Mozilla’s recommendations.

With the Cookie-Flag module.

In this quick and practical example we will compile and deploy our first NGINX modules: ModSecurity and Cookie-Flag. All you have to do is reproduce these steps to add more modules.

Keep in mind that this article is above all, a way to remember what I did for myself. I am not a security expert and there can be mistakes. It is also a way for me to get help and advices on how I do things. Maybe you will tell me: “Oh my God, don’t do it like that, it’s really bad”. And if by the way, I can help a few people, then it’s perfect.

Prerequisites

  1. An NGINX server in its Open Source version.
  2. A text editor.
  3. The make command and everything that goes with it.

Installation

LibModSecurity

First of all, we are going to get back our firewall. You can either, download it from the official repositories of your GNU/Linux distribution:

sudo pacman -Syu libmodsecurity # Arch Linuxsudo apt-get install libmodsecurity3 # Ubuntu

Or compile it from the sources:

$ git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity$ cd ModSecurity$ git submodule init
$ git submodule update
$ ./build.sh
$ ./configure
$ make
$ make install
$ cd ..

Download the NGINX sources.

To build the modules, it is necessary to get the NGINX sources. It is also possible to compile NGINX directly with the selected modules. But here, we will do this dynamically and especially after installation. This allows us to use modules on a server already installed and deployed.

Let’s check the installed version:

$ nginx -v
nginx version: nginx/1.17.3

Then, download the archive of this version and excrat it:

$ wget http://nginx.org/download/nginx-1.17.3.tar.gz

$ tar zxvf nginx-1.17.3.tar.gz

Download the ModSecurity/NGINX connector.

We need the connector that connects NGINX to ModSecurity. ModSecurity does not only work with the NGINX server. And nothing is provided for communicate with them.

$ git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git

Download the Cookie-Flag module.

In our example, we also wanted to add the Cookie-Flag module.

$ git clone https://github.com/AirisX/nginx_cookie_flag_module$ git checkout v1.1.0

Configuration and compilation of the dynamic modules.

All we have to do now is configure and compile the dynamic modules using NGINX sources.

$ cd ../nginx-YOURVERSION$ ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx --add-dynamic-module=../nginx_cookie_flag_module$ make modules

Once finished, moved your modules to the NGINX directory:

$ mkdir -p /etc/nginx/modules$ cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules
$ cp objs/ngx_http_cookie_flag_filter_module.so /etc/nginx/modules

And add the modules loading in the /etc/nginx/nginx.conf file:

load_module modules/ngx_http_modsecurity_module.so;
load_module modules/ngx_http_cookie_flag_filter_module.so;

I’m not sure it comes with the libmodsecurity package, but you also need the ModSecurity configuration file, so in the doubt:

$ mkdir /etc/nginx/modsec$ wget -P /etc/nginx/modsec/ https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended$ mv /etc/nginx/modsec/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf

Finally, add to your server’s blocks something like this:

server {[...]# The NGINX module to add cookie flags
set_cookie_flag Secret HttpOnly secure SameSite;
set_cookie_flag * HttpOnly;
set_cookie_flag SessionID SameSite=Lax secure;
set_cookie_flag SiteToken SameSite=Strict;
[...] # Enable ModSecurity
modsecurity on;
[...]}

Let’s restart NGINX:

$ sudo nginx -t
2019/02/08 13:42:49 [notice] 15008#15008: ModSecurity-nginx v1.0.0 (rules loaded inline/local/remote: 0/683/0)
$ sudo systemctl restart nginx

You have now added your two new modules to your NGINX server. Congratulations!

The ModSecurity module is now installed. However, it is only in detection mode and without any rules.

OWASP ModSecurity Core Rule Set.

In order to block the suspicious request, set the SecRuleEngine parameter at On in the /etc/nginx/modsec/modsecurity.conf file:

$ sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsec/modsecurity.conf

I use the OWASP ModSecurity Core Rule Set. OWASP (Open Web Application Security Project) is a free and open source community working for the Internet’s security and provides these types of rules with this project.

Let’s get the project from GitHub:

$ git clone https://github.com/SpiderLabs/owasp-modsecurity-crs/
$ cd owasp-modsecurity-crs

And checkout to the latest stable version (v3.1.1 at this time):

$ git checkout v3.1.1

Then move all its rules to /usr/local and rename the configuration file into crs-setup.conf.

$ sudo cp -r ../owasp-modsecurity-crs /usr/local/owasp-modsecurity-crs-3.1.1$ sudo cp /usr/local/owasp-modsecurity-crs-3.1.1/crs-setup.conf.example /usr/local/owasp-modsecurity-crs-3.1.1/crs-setup.conf

It also necessary to rename some rules (by removing the .example):

rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example
rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example

Create the inclusion file for these rules:

$ sudo vim /etc/nginx/modsec/main.confInclude "/etc/nginx/modsec/modsecurity.conf"# OWASP CRS v3 rules
Include /usr/local/owasp-modsecurity-crs-3.1.1/crs-setup.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-901-INITIALIZATION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-910-IP-REPUTATION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-912-DOS-PROTECTION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-913-SCANNER-DETECTION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-921-PROTOCOL-ATTACK.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/REQUEST-949-BLOCKING-EVALUATION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-950-DATA-LEAKAGES.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-980-CORRELATION.conf
Include /usr/local/owasp-modsecurity-crs-3.1.1/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf

And don’t forget to import this main file containing all this rules into the NGINX configuration. In your nginx.conf file:

# Enable ModSecurity
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;

Now you have ModSecurity configured to block suspicious requests according to OWASP CRS.

Originally published at https://www.aimd.tech on February 9, 2019.

--

--