How to Install ModSecurity 3, OWASP CRS with Nginx on Ubuntu 22.04 or 20.04

ModSecurity 3 is a powerful open-source Web Application Firewall (WAF) that safeguards web applications from various threats. This guide will walk you through the steps to install Modsecurity 3, OWASP CRS with Nginx on Ubuntu 22.04 Jammy Jellyfish or its older stable release of Ubuntu 20.04 Focal Fossa.

Key Advantages of ModSecurity 3:

  • Advanced Protection: ModSecurity 3 defends web applications against attacks, including SQL injection, Cross-Site Scripting (XSS), and Local File Inclusion (LFI).
  • Seamless NGINX Integration: It integrates seamlessly with NGINX, enhancing security without sacrificing performance.
  • Custom Rule Support: Users can implement custom rulesets, tailoring security measures to meet the specific needs of each web application.
  • Detailed Logging: With comprehensive logs of all HTTP transactions, it facilitates efficient traffic monitoring and the identification of potential security threats.
  • Open-Source & Community-Driven: Supported by a vibrant community, ModSecurity 3 is continuously improved, providing a transparent and adaptable security solution.

Deploying ModSecurity 3 with NGINX on Ubuntu 22.04 Jammy Jellyfish or Ubuntu 20.04 Focal Fossa offers an effective security solution for your web applications. Follow this guide for detailed installation instructions, laying the groundwork for robust web application security.

Pre-installation Steps For Modsecurity 3 with Nginx on Ubuntu 22.04 or 20.04

Before beginning the ModSecurity installation, prepare your server for the upcoming tasks. Update your system and ensure you have the latest version of Nginx, a high-performance web server and reverse proxy server, to minimize compatibility issues and security vulnerabilities, smoothing the installation process.

Step 1: Update Ubuntu Before Modsecurity 3 Installation

The first step towards a secure and efficient server is keeping it up-to-date. This ensures all software packages have the latest security patches and performance improvements. Execute the following command to update your system:

sudo apt update && sudo apt upgrade 

This command first updates the package lists for upgrades (sudo apt update).

Step 2: Remove Pre-existing Nginx Installation (Situational)

If you have a pre-existing Nginx installation, we recommend removing it and installing the latest version from a custom PPA maintained by Ondřej Surý. This version has additional dynamic modules, such as the Brotli module, for improved compression.

First, stop the current Nginx service with the following:

sudo systemctl stop nginx

Then, remove the existing Nginx installation with the following commands:

sudo apt purge nginx -y && sudo apt autoremove nginx -y

Here, the purge option completely removes the Nginx package and its configuration files. The autoremove command removes any packages that were automatically installed to satisfy Nginx’s dependencies but are no longer needed.

Step 3: Add the Latest Nginx PPA (Optional)

Remove the outdated Nginx service, then add a new, current PPA (Personal Package Archive) for Nginx. Choose between a stable or mainline version; opt for the mainline version to access the latest features and improvements.

To add the stable PPA, execute:

sudo add-apt-repository ppa:ondrej/nginx-stable -y

Or for the mainline PPA, use:

sudo add-apt-repository ppa:ondrej/nginx-mainline -y

Step 4: Update Packages Index After Nginx PPA Import on Ubuntu

After importing the desired repository, updating your APT sources list is necessary. This ensures the system knows about the new packages in the added repository. Update your sources list with the following:

sudo apt update

Now, install Nginx with the following command:

sudo apt install nginx

During the installation, you may be prompted to keep or replace your existing /etc/nginx/nginx.conf configuration file. It’s generally recommended to keep your current configuration file by pressing n.

Step 5: Uncomment DEB-SRC Nginx Source on Ubuntu

The PPA installation process does not include the Nginx source code by default. You must enable a specific feature and manually download the Nginx source code to compile Modsecurity later in this tutorial.

Open the configuration file located in /etc/apt/sources.list.d:

sudo nano /etc/apt/sources.list.d/ondrej-ubuntu-nginx-mainline-*.list

Find the line that starts with # deb-src and uncomment it (i.e., remove the #). If you use a different third-party repository, replace the path in the command with the appropriate one:

# deb-src jammy main
Screenshot depicting # removal from src in Nginx mainline for Modsecurity 3 installation on Ubuntu 22.04 or 20.04.
Illustrative example demonstrating how to edit src in Nginx mainline during the installation of Modsecurity 3 on Ubuntu 22.04 or 20.04.

Once done, save the file by pressing CTRL+O and then exit by pressing CTRL+X.

If you’re more comfortable with command-line utilities, you can also use the sed command to uncomment the source line:

sudo sed -i 's/# deb-src/deb-src/g' /etc/apt/sources.list.d/ondrej-ubuntu-nginx-mainline-*.list

Finally, update the repository list using the following command:

sudo apt update

This command ensures that your system acknowledges adding the Nginx source code to the repository, making it available for further operations.

Download Nginx Source Code on Ubuntu

To seamlessly integrate ModSecurity with Nginx, we must compile the ModSecurity dynamic module against the Nginx source code. To do this, we first need to download and store the Nginx source code in a specific directory (/usr/local/src/nginx). This section walks you through creating the necessary directories, installing dependencies, downloading the source code, and verifying that the source version matches the installed Nginx version.

Step 1: Create Directory Structure

First, create a directory to download and store the Nginx source code. Here’s the command to create the directory and navigate into it:

sudo mkdir /usr/local/src/nginx && cd /usr/local/src/nginx

This command creates the directory /usr/local/src/nginx and then changes the current directory to this newly created directory.

Step 2: Install Required Packages and Download Nginx Source

Before we can download the source code, we need to install a package called dpkg-dev. This package provides several development tools to unpack, build, and upload Debian source packages. Install it with the following command:

sudo apt install dpkg-dev -y

We’re ready to download the Nginx source code with the necessary tools. Use the following command to accomplish this:

sudo apt source nginx

While running this command, you might encounter an error message. Don’t worry; this error message can be safely ignored.

Nginx source download screenshot for installing Modsecurity 3 on Ubuntu 22.04 or 20.04.
A visual guide on downloading the Nginx source for Modsecurity 3 installation on Ubuntu 22.04 or 20.04.

Step 3: Verifying the Source Version on Ubuntu

After downloading the source code, it’s essential to ensure that the downloaded source version matches the installed Nginx version. Differences between these versions can lead to compatibility issues, so this verification step is crucial.

First, list the files in the current directory to confirm you have downloaded the source code:

Screenshot showing Nginx source code available for Modsecurity 3 installation on Ubuntu 22.04 or 20.04.”
Visual confirmation of the Nginx source code necessary for Modsecurity 3 installation on Ubuntu 22.04 or 20.04.

You should see several files and directories related to Nginx in the output.

Next, confirm that the source package matches the Nginx version installed on your Ubuntu system. You can check the installed Nginx version with the following command:

The output will display your installed Nginx version. Ensure this version matches the source version you’ve downloaded. If they don’t match, you’ll need to download the correct version of the Nginx source code.

nginx -v

The output will display your installed Nginx version. Ensure this version matches the source version you’ve downloaded. If they don’t match, you’ll need to download the correct version of the Nginx source code.

Verification screenshot of matching installed binary Nginx and downloaded Nginx source for Modsecurity 3 on Ubuntu 22.04 or 20.04.
A Screenshot confirms that the installed binary Nginx and the downloaded Nginx source match for Modsecurity 3 installation on Ubuntu 22.04 or 20.04.

Install libmodsecurity3 for ModSecurity 3 on Ubuntu 22.04 or 20.04

ModSecurity is an effective firewall for web applications, and libmodsecurity3 is its core component that handles HTTP filtering. This section will guide you through obtaining and installing this essential software package.

Step 1: Clone the ModSecurity 3 Repository on Ubuntu

First, fetch the libmodsecurity3 source code from its GitHub repository using Git, a popular distributed version control system. If your system doesn’t already have Git installed, use the following command to add it:

sudo apt install git

Before we clone the repository, it’s a good practice to adjust the ownership of the directory to avoid the need for root privileges (sudo) for most commands:

sudo chown -R $user:$user /usr/local/src/

his command recursively changes the ownership of /usr/local/src/ directory to the current user.

Next, let’s clone the libmodsecurity3 repository. We’ll use a shallow clone (--depth 1) to save bandwidth and storage. This means we’ll only fetch the latest revision of the v3/master branch:

git clone --depth 1 -b v3/master --single-branch /usr/local/src/ModSecurity/

After cloning the repository, change your working directory to the newly cloned repository:

cd /usr/local/src/ModSecurity/

Step 2: Install libmodsecurity3 Dependencies on Ubuntu

The compilation of libmodsecurity3 requires several dependencies. Install them with the following command:

sudo apt install 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 libpcre++-dev libpcre2-16-0 libpcre2-dev libpcre2-posix3 -y

To successfully compile Nginx with ModSecurity 3 from version 1.21.4 onwards, you must have these dependencies. Although this step can cause issues, installing the correct dependencies will resolve them in nearly all circumstances.

Next, initialize and update the Git submodules with the following commands:

git submodule init
git submodule update

Step 3: Build ModSecurity Environment on Ubuntu

Now that we’ve prepared our workspace, it’s time to build the ModSecurity environment. First, run the build script:

Terminal Screenshot: Successful Output After Modsecurity 3 Installation on Ubuntu 22.04 or 20.04
Screenshot showing the terminal output after running for installing Modsecurity 3 on Ubuntu 22.04 or 20.04.

Then, configure the environment:


During this process, you may encounter an error stating fatal: No names found, cannot describe anything. Don’t worry this error message can be safely ignored.

Configure Terminal Output Screenshot for Modsecurity 3 & Nginx Installation on Ubuntu 22.04 or 20.04
Screenshot showcasing example configure terminal output during Modsecurity 3 and Nginx installation on Ubuntu 22.04 or 20.04.

Step 4: Compile the ModSecurity Source Code on Ubuntu

Having built and configured the environment for libmodsecurity3, we’re ready to compile it. Here’s the command to do so:


For those working on high-performance servers, you can speed up the compilation process by running make with the -j option followed by the number of CPU cores your server has. For instance, if your server has six CPU cores, you could use:

make -j 6
Terminal Screenshot: ‘make’ Command Output for Modsecurity 3 & Nginx Installation on Ubuntu 22.04 or 20.04
Screenshot displaying the terminal output for the ‘make’ command during Modsecurity 3 and Nginx installation on Ubuntu 22.04 or 20.04.

Step 5: Install Compiled Code For Modsecurity 3 on Ubuntu

After compiling the source code, the last step is to install it:

sudo make install

This command installs libmodsecurity3 to /usr/local/modsecurity/, which is the directory you’ll reference later in this guide.

Screenshot: Terminal Output for ‘sudo make install’ Command, Modsecurity 3 & Nginx on Ubuntu 22.04 or 20.04
Screenshot of terminal output for the ‘sudo make install’ command during Modsecurity 3 and Nginx installation on Ubuntu 22.04 or 20.04.

Install ModSecurity-nginx Connector on Ubuntu 22.04 or 20.04

In this section, we’ll guide you through installing the ModSecurity-nginx connector. This vital component is the liaison between Nginx, a popular web server software, and ModSecurity, ensuring seamless communication.

Step 1: Clone the ModSecurity-nginx Repository on Ubuntu

First, we need to fetch the source code of the ModSecurity-nginx connector. We do this by cloning the repository from GitHub. Similar to the previous step of cloning the libmodsecurity3 repository, use the following command to clone the ModSecurity-nginx repository:

git clone --depth 1 /usr/local/src/ModSecurity-nginx/

This command fetches only the latest revision of the ModSecurity-nginx repository, saving bandwidth and storage.

Step 2: Install ModSecurity-nginx Dependencies on Ubuntu

Next, we need to navigate to the Nginx source directory. You can do this by executing the following cd command:

cd /usr/local/src/nginx/nginx-1.*.*

In the Nginx source directory, we’ll install the dependencies required for the ModSecurity-nginx connector. Run this command to fetch and install the necessary dependencies:

sudo apt build-dep nginx && sudo apt install uuid-dev

Step 3: Compile ModSecurity-nginx Connector

With the dependencies in place, we can compile the ModSecurity-nginx connector. For this, we need to run the configure command with the --with-compat flag and --add-dynamic-module option:

./configure --with-compat --add-dynamic-module=/usr/local/src/ModSecurity-nginx

The --with-compat flag ensures compatibility with various systems, while the --add-dynamic-module option specifies the location of the ModSecurity-nginx connector.

Terminal output screenshot displaying dynamic module link creation for Modsecurity-Nginx on Ubuntu 22.04 or 20.04.
Screenshot of terminal output showcasing the process of generating a dynamic module link for Modsecurity-Nginx on Ubuntu.

After configuring the environment, create the dynamic modules by running the make command:

make modules

At the end of the process, your terminal should see something similar:

Terminal output screenshot for 'make modules' command with Modsecurity Nginx Connector on Ubuntu 22.04 or 20.04.
Example terminal output for compiling modules for the Modsecurity Nginx Connector on Ubuntu 22.04 or 20.04.

Step 4: Moving the Dynamic Module on Ubuntu

The final step in this process is moving the dynamic module to the appropriate directory. The make modules command creates a dynamic module at the location objs/ You need to move this module to the /etc/nginx/modules/ directory. Use the following command to accomplish this:

sudo cp objs/ /etc/nginx/modules/

It’s important to note that you can store the dynamic module anywhere, provided you specify the full path when loading it.

Configure the ModSecurity-nginx Connector with Nginx on Ubuntu 22.04 or 20.04

After successfully installing the ModSecurity-nginx connector, load and appropriately configure it into Nginx. Edit your Nginx configuration file at /etc/nginx/nginx.conf to make ModSecurity 3 operational with your Nginx web server.

Step 1: Enable ModSecurity in nginx.conf

To start, you need to specify the location of the ModSecurity module in the nginx.conf file. To do this, open the nginx.conf file using a text editor. For this example, we’ll be using nano:

sudo nano /etc/nginx/nginx.conf

At the top of the file, add the following line:

load_module modules/;

This command instructs Nginx to load the ModSecurity module. If you stored the module in a different location, include the full path in this command.

Next, add the following code under the http {} section:

modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/modsec-config.conf;

The above commands enable ModSecurity and specify the location of the ModSecurity rules file. Save the changes (Ctrl+O) and exit the file (Ctrl+X).

Step 2: Create Directory and Files for ModSecurity 3 on Ubuntu

You need to create a directory to store configuration files and future rules. The following command will create the /etc/nginx/modsec directory:

sudo mkdir /etc/nginx/modsec/

Next, copy the sample ModSecurity configuration file from the cloned Git directory to the directory you’ve just created:

sudo cp /usr/local/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf

Now, let’s modify the modsecurity.conf file. By default, the ModSecurity rule engine operates in DetectionOnly mode, which detects malicious behavior but does not block it. To change this behavior, open the modsecurity.conf file:

sudo nano /etc/nginx/modsec/modsecurity.conf

Locate the line SecRuleEngine DetectionOnly and change it to:

SecRuleEngine On

Next, locate the SecAuditLogParts line:

# Log everything we know about a transaction.
SecAuditLogParts ABIJDEFHZ

The current configuration is not correct. Modify the line to the following:

SecAuditLogParts ABCEFHJKZ

Now, save (Ctrl+O) and exit (Ctrl+X) the file.

Step 3: Create modsec-config.conf File on Ubuntu

The next step is to create a modsec-config.conf file. This file will include the modsecurity.conf file and other rule sets, such as the OWASP CRS, later on. Create and open the file with this command:

sudo nano /etc/nginx/modsec/modsec-config.conf

Once inside the file, add the following line:

Include /etc/nginx/modsec/modsecurity.conf

Save (Ctrl+O) and exit (Ctrl+X) the file.

Finally, copy ModSecurity’s unicode.mapping file using the cp command:

sudo cp /usr/local/src/ModSecurity/unicode.mapping /etc/nginx/modsec/

Step 4: Validating Nginx Modsecurity 3 Configuration on Ubuntu

Before proceeding, it’s crucial to validate your configuration. Run the following command to perform a dry run of the Nginx service:

sudo nginx -t

If you have set up everything correctly, the following message should appear:

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

The output confirms that the syntax in your Nginx configuration file is correct, signaling a successful configuration test. Review the previous steps, ensuring accurate command entry and file paths should you encounter errors.

Step 5: Apply Configuration Changes with Nginx on Ubuntu

Once you’ve validated your configuration and ensured no syntax errors, you need to restart the Nginx service for the changes to take effect. This is a critical step in making ModSecurity operational.

Use the systemctl command to restart the Nginx service:

sudo systemctl restart nginx

This command instructs your system to stop and immediately start the Nginx service. With this, your Nginx service should now have the ModSecurity WAF enabled and operational.

Install OWASP Core Rule Set for ModSecurity 3 on Ubuntu 22.04 or 20.04

This section will enhance our web server’s security by deploying the OWASP Core Rule Set (CRS) for ModSecurity. While ModSecurity 3 is powerful, it requires a set of rules to function effectively.

The OWASP CRS offers a respected and widely accepted set of rules for web application firewalls (WAFs), serving as a robust protective barrier against most emerging internet threats. It identifies and blocks potential attacks, providing a fundamental resource upon which many similar systems build their rules. Adopting the OWASP CRS sets you on the right path to securing your server.

Step 1: Navigate to ModSecurity 3 Directory on Ubuntu

To begin, we need to navigate back to the ModSecurity directory we created in the previous steps:

cd /etc/nginx/modsec

Optionally, you can change the ownership of this directory to your current user to avoid having to use the sudo command for subsequent steps:

sudo chown -R $USER:$USER /etc/nginx/modsec/

Step 2: Download OWASP CRS Archive on Ubuntu

Next, we’ll download the OWASP CRS archive using the wget command. The latest stable release is 3.3.4 at the time of writing, but you should check the OWASP Release tag page for the most recent version.


Be sure to change the above command’s v3.3.4 to either 3.3.5 or 3.3.6 in the future, always confirm you have the latest stable release! The command provided above serves as an example only.”

Download the nightly build version to stay updated with the latest developments. This version includes the most recent changes and improvements. However, it may be less stable and will require frequent updates. Only advanced users should use this version.


Opt for the nightly version only if you are confident in your ability to navigate through frequent updates and false positives vigilantly. Under most circumstances, it is advisable to use the latest stable release.

Step 3: Extract OWASP Core Rule Set Archive on Ubuntu

Once the download is complete, extract the archive using the tar command:

tar -xvf v3.3.4.tar.gz

Remember to replace v3.3.4.tar.gz with the name of the file you downloaded if you’re using a different version.

Step 4: Configure OWASP CRS on Ubuntu

Like the ModSecurity configuration we dealt with earlier, the OWASP CRS has a sample configuration file we need to rename. Using the cp command, we’ll create a copy of this file, preserving the original as a backup:

sudo cp /etc/nginx/modsec/coreruleset-3.3.4/crs-setup.conf.example /etc/nginx/modsec/coreruleset-3.3.4/crs-setup.conf

Step 5: Enable OWASP CRS Rules with Modsecurity 3 on Ubuntu

To enable the OWASP CRS rules, we need to modify the modsec-config.conf file:

sudo nano /etc/nginx/modsec/modsec-config.conf

In this file, add the following two lines to include the CRS configuration and rules:

Include /etc/nginx/modsec/coreruleset-3.3.4/crs-setup.conf
Include /etc/nginx/modsec/coreruleset-3.3.4/rules/*.conf

Save the file (CTRL+O) and exit (CTRL+T).

Terminal screenshot displaying includes with Core Rule Set and Modsec-config on Ubuntu 22.04 or 20.04.
Terminal output example for setting up includes with the Core Rule Set and Modsec-config on Ubuntu 22.04 or 20.04.

Remember to replace coreruleset-3.3.4 with the version you downloaded if it’s different.

Save the changes (Ctrl+O) and exit the text editor (Ctrl+X).

sudo nginx -t

Step 6: Validating the Configuration and Restarting Nginx

Now that we’ve made these significant changes to our Nginx configuration, we must validate everything to ensure no syntax errors or misconfigurations. This validation step is like a “dress rehearsal” for the actual launch of the updated service.

To perform this “dry run”, use the following command:

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

This message tells us that our configuration is correct and that our changes will not disrupt service.

However, if you encounter error messages, carefully review them for clues about what might have gone wrong. The error messages are often informative and can guide you toward the problematic section of your configuration files.

We are ready to make these changes live with the successful dry run. For the new configuration to take effect, we need to restart the Nginx service:

sudo systemctl restart nginx

Understanding and Utilizing the OWASP Core Rule Set with Modsecurity 3 and Ubuntu

With the installation and setup of ModSecurity and the OWASP Core Rule Set (CRS) on your Nginx web server completed, it’s time to delve deeper into understanding and making use of the CRS. The CRS is rich with options, and while the default settings provide immediate, broad-spectrum protection for most servers, thoroughly exploring its capabilities will help you fine-tune its functionality to suit your specific needs.

Navigate CRS Configuration

For a start, let’s familiarize ourselves with the CRS configuration file. This is where you can tweak the various settings provided by the CRS. To open the configuration file, use the following command:

sudo nano /etc/nginx/modsec/coreruleset-3.3.4/crs-setup.conf

This file contains many options, each with detailed comments explaining their functions. Dive into this wealth of information to gain invaluable insights into the CRS’s operation and discover how to tailor it to meet your requirements.

Scoring Modes in OWASP CRS

The CRS operates using a scoring system. There are two primary modes of operation:

Anomaly Scoring Mode

# -- [[ Anomaly Scoring Mode (default) ]] --

The recommended mode is the default. Each matching rule for a request or response in this mode increases an ‘anomaly score’. After evaluating all inbound and outbound rules, the system checks the total anomaly score against a threshold. If the score surpasses the threshold, it triggers a disruptive action—typically returning an HTTP 403 error. This mode allows for flexible blocking policy settings and generates informative audit logs.

Self-Contained Mode

# -- [[ Self-Contained Mode ]] --

When a rule matches this mode, the system immediately stops further evaluation. This mode reduces resource usage, offers less flexibility in blocking policy, and produces less informative audit logs. The system logs only the first detected threat, mirroring many Intrusion Detection Systems (IDS). Generally, we recommend Anomaly Scoring Mode for most users for its flexibility and informative nature.

Paranoia Levels: Balancing Security and Usability

A unique feature of the CRS is its paranoia levels. These levels allow you to control how many rule checks contribute to your anomaly scores, essentially letting you tune the sensitivity of the CRS.

There are four paranoia levels:

  • Paranoia Level 1: The default level recommended for most users. It enables most core rules and should rarely trigger false positives (FPs) or legitimate requests mistakenly identified as malicious.
  • Paranoia Level 2: Designed for advanced users, this level enables additional rules, such as regex-based SQL and XSS injection protections. Some false positives may occur at this level.
  • Paranoia Level 3: For expert users, this level enables even more rules and limits on special characters used. Expect to handle more false positives at this level.
  • Paranoia Level 4: Only recommended for exceptional circumstances. This level restricts special characters further and is likely to produce many false positives.

Paranoia levels help strike a balance between security and usability. While high paranoia levels offer enhanced security, they may block legitimate traffic and trigger false alarms. If you choose to increase the paranoia level, plan to implement exclusion rules for specific requests and applications to minimize false positives.

Customizing OWASP CRS Rules (Additional Learning)

An advantage of the OWASP CRS is its flexibility, allowing you to create and modify rules to meet your needs. Let’s take a closer lLet’st how you might approach this task.

Opening the Rule Files

The rule files are located in the rules directory under the coreruleset-3.3.4 directory. These files contain rules the CRS uses to inspect incoming and outgoing HTTP traffic. You can open these files to view the existing rules and add custom ones.

sudo nano /etc/nginx/modsec/coreruleset-3.3.4/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

This opens the file containing the exclusion rules processed before the CRS rules.

Understanding Rule Structure

Each rule in ModSecurity has a unique structure. A typical rule might look like this:

SecRule ARGS "@rx attack" "id:1234,phase:2,t:none,log,deny,msg:'Attempted attack'"

Here’s a brief breakdown of the rules components:

  • SecRule: The directive that begins the rule.
  • ARGS: The variable to be inspected. ARGS refers to all arguments, including GET, POST, and cookies.
  • "@rx attack": The operator and its argument. @rx is a regular expression match, and attack is the pattern to match.
  • "id:1234,phase:2,t:none,log,deny,msg:'Attempted attack'": The rule’s action list. Includes a unique ID for the rule, the phase in which the rule operates, transformations to apply (t:none means no transformations), the action to take if the rule matches (in this case, log the event and deny the request), and a message to log if the rule matches.

Creating Custom Rules

To create a custom rule, decide which variable to inspect, identify the pattern to search for, and determine the action to take upon finding a match. For instance, if you wish to block requests with a particular suspicious user-agent string, create a rule that examines the USER_AGENT variable for the suspicious string and denies the request upon detection.

SecRule REQUEST_HEADERS:User-Agent "@rx suspicious-user-agent" "id:1235,phase:1,t:none,log,deny,msg:'Suspicious User-Agent Detected'"

This rule will block requests with the ‘suspicious-user-agent” string in its user-‘gent header.

To create custom rules, you must thoroughly understand HTTP, the OWASP CRS, and your application’s behavior and adjust as needed to prevent disruption to legitimate traffic.

Verifying OWASP CRS Implementation with Modsecurity 3 on Ubuntu 22.04 or 20.04

After successfully setting up the OWASP CRS on your server, it’s vital to test implementation to ensure it’s functioning as intended. This step is crucial as it verifies the effective deployment of the security rules and allows troubleshooting any potential issues that might have occurred during the setup.

Performing a Test Request to the Webserver

To confirm the efficacy of the OWASP CRS, craft a specific URL designed to trigger an alert with correct rule implementation. This URL should include a query string that tries to execute a command, clearly violating security rules.

Replace with your actual domain name. This URL attempts to pass the /bin/bash command through the exec parameter in the query string.

Interpreting the Response

If OWASP CRS is correctly set up and operational, it should identify this malicious request and respond with a 403 Forbidden error. This error implies that the server understood the request but refused to authorize it, which in this case, is a result of the ModSecurity rule violation.

Screenshot showing 403 status after testing Modsecurity 3 with OWASP CRS on Ubuntu 22.04 or 20.04.
A Screenshot captured post-testing Modsecurity 3 with OWASP CRS on Ubuntu, displaying a 403 status.

The image above shows a 403 Forbidden error page, which you should see if you’ve properly confiyou’veModSecurity and OWASP CRS. This configuration actively protects your server from malicious requests.


If you don’t receive a 403 Forbidden error indicates that something is amiss. The most common issue is forgetting to switch ModSecurity from DetectionOnly mode to On. DetectionOnly mode logs the threats but doesn’t block them.

Dealing with False Positives and Custom Rule Exclusions with Modsecurity 3, OWASP CRs on Ubuntu 22.04 or 20.04

In the realm of cybersecurity, the deployment of the OWASP CRS alongside ModSecurity often serves as an effective line of defense. However, it can lead to instances of false positives, which can consume a significant amount of your time to manage. Though potentially overwhelming, this time expenditure is often justified by the valuable protection provided.

Navigating False Positives

Striking a delicate balance between security and usability is crucial. Setting the paranoia level of ModSecurity rules too high may yield many false positives. Therefore, it is wise to begin with a lower paranoia level. This approach minimizes false positives, allowing the rule set to operate for several weeks to months. You will become familiar with the system’s behavior and systems during this initial phase. Once comfortable with the output, gradually increase the paranoia level to prevent a sudden flood of false positives.

Excluding Common False Positives

ModSecurity offers a mechanism for whitelisting common actions that often trigger false positives. This feature proves especially useful for applications interacting frequently with your server.

Below is an example of a default rule that whitelists these actions:

#SecAction \
# "id:900130,\
#  phase:1,\
#  nolog,\
#  pass,\
#  t:none,\
#  setvar:tx.crs_exclusions_cpanel=1,\
#  setvar:tx.crs_exclusions_dokuwiki=1,\
#  setvar:tx.crs_exclusions_drupal=1,\
#  setvar:tx.crs_exclusions_nextcloud=1,\
#  setvar:tx.crs_exclusions_phpbb=1,\
#  setvar:tx.crs_exclusions_phpmyadmin=1,\
#  setvar:tx.crs_exclusions_wordpress=1,\
#  setvar:tx.crs_exclusions_xenforo=1"

To whitelist certain applications, uncomment the corresponding lines and leave the (1) number intact. For services that you do not use, for instance, Xenforo, change the (1) to (0). This action ensures that you do not whitelist unnecessary rules.

Streamlining the Syntax

For a cleaner syntax, you can modify the command to include only the applications you wish to whitelist. For example, if you use WordPress, phpBB, and phpMyAdmin, the command would look like this:

SecAction \

This streamlined syntax makes it easier to read and maintain.

Addressing Custom Exclusions

To handle custom exclusions, you need to activate a specific file. This step involves renaming the REQUEST-900-EXCLUSION-RULES-BEFORE-CRS-SAMPLE.conf file using the cp command:

sudo cp /etc/nginx/modsec/coreruleset-3.4-dev/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example /etc/nginx/modsec/coreruleset-3.4-dev/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

Each exclusion rule must have a unique id. Repeating a rule id will cause an error during the Nginx service testing phase.

Whitelisting Specific Paths and IP Addresses

There are instances where specific paths, often associated with certain applications, tend to trigger false positives. In such situations, you can whitelist these paths to eliminate unnecessary alerts. Here’s how you can do it:

SecRule REQUEST_URI "@beginsWith /wp-load.php?wpmudev" "id:1544,phase:1,log,allow,ctl:ruleEngine=off

SecRule REQUEST_URI "@beginsWith /ngx_pagespeed_beacon" "id:1554,phase:1,log,allow,ctl:ruleEngine=off"

The specified path will automatically allow any URL that begins with it, reducing false positives in the above example.

You may occasionally need to whitelist certain IP addresses known to be safe. ModSecurity offers options for this task.

SecRule REMOTE_ADDR "^195\.151\.128\.96" "id:1004,phase:1,nolog,allow,ctl:ruleEngine=off"

## or ###

SecRule REMOTE_ADDR "@ipMatch,," "phase:1,id:1313413,allow,ctl:ruleEngine=off"

In these examples, the @ipMatch directive can be used to whitelist entire subnets, increasing the versatility of your whitelisting strategy. If you need to blacklist a specific IP address or subnet, replace allow with deny.

Refining Rule Exclusions

While whitelisting entire paths or IP addresses can reduce false positives, it might also unintentionally allow potentially harmful requests. A more precise approach is to disable specific rules that trigger false positives, rather than whitelisting entire paths. However, this approach requires more time and testing to fine-tune.

For instance, let’s say the rules wlet’sDs 941000 and 942999 keep triggering false alerts for your /admin/ area. You can disable these specific rules by using the ruleRemoveById directive as shown below:

SecRule REQUEST_FILENAME "@beginsWith /admin" "id:1004,phase:1,pass,nolog,ctl:ruleRemoveById=941000-942999"

With this configuration, only the specified rules will be disabled for the /admin/ path, maintaining high protection for the rest of your application.

Configure Log Rotation for ModSecurity 3 on Ubuntu 22.04 or 20.04

When working with a web application firewall like ModSecurity 3, keeping an eye on the logs is crucial. However, these logs can quickly grow, potentially taking up significant storage space on your server. This growth can also make it more difficult to find specific entries when troubleshooting or analyzing security events. To manage this, we can set up a process known as log rotation.

Creating the ModSecurity Log Rotation File

To begin with, let’s create a configuration file for the log rotation process. This file will define how and when the log rotation happens. We can place this file in the /etc/logrotate.d/ directory, which is where the logrotate utility looks for its configuration files.

Use the following command to create and open a new file called modsec:

sudo nano /etc/logrotate.d/modsec

The nano command launches a text editor in the terminal, allowing you to create and edit the file directly.

Defining the Log Rotation Rules

In this file, we will define rules for rotating the ModSecurity logs. Copy and paste the following block of code into the file:

        rotate 31

Let’s break down what each line in this block of code does:

  • /var/log/modsec_audit.log: This is the file that we want to rotate. It’s the location of the ModSecurity audit log.
  • rotate 31: This directive means that logrotate should keep 31 rotated log files before discarding the oldest ones.
  • daily: This instructs logrotate to rotate the log file once every day.
  • missingok: If the log file is missing, logrotate will not output an error message.
  • compress: This directive tells logrotate to compress the rotated log files to save space.
  • delaycompress: This postpones compression of the previous log file to the next rotation cycle. This can be helpful if some programs are still writing to the file.
  • notifempty: If the log file is empty, logrotate will not rotate it.

These settings rotate your ModSecurity logs daily, maintaining a month’s worth of logs the settings to meet your needs. For instance, to keep only a week’s worth of logs, weeks rotate from 31 to 7. However, managing and analyzing a weekly log file can be cumbersome due to its potentially large size, so daily rotation is recommended for ModSecurity.

Prevent Nginx Updates with APT-HOLD on Ubuntu 22.04 or 20.04

As we navigate the complex world of managing web servers, it’s important to recognize that while generally beneficial, automated system updates can sometimes interfere with our carefully configured setups. This is especially true when we have customized or highly specific configurations, like Nginx with ModSecurity. In such cases, automated updates to Nginx can potentially overwrite our configurations or introduce compatibility issues with the current setup. Hence, it might be beneficial to prevent automatic updates to Nginx. We can achieve this by using the APT package management system feature known as “APT-HOLD”.

Understanding APT-“OLD

The apt-mark command, a utility within the APT package management system, lets users manipulate package status. Its “hold” option marks “packages” as held back, preventing their update.

Applying APT-HOLD to Nginx

To put Nginx on hold and thus prevent it from being automatically updated, we can use the apt-mark command as follows:

sudo apt-mark hold nginx

After running this command, the system will hold back any updates for the Nginx package until you manually change this setting. This will ensure that automatic system updates keep your configuration intact and unaffected.

Reverting APT-HOLD

You may need to update Nginx at some point, perhaps to leverage new features or implement security patches. Remove the hold on Nginx updates by using the unhold option:

sudo apt-mark unhold nginx

This action returns the package to regular status, allowing updates the next time you upgrade your system’s packages and systems any issues between Nginx and Modsecurity, such as recompiling.

Closing Thoughts

Through our proactive journey, we have effectively incorporated ModSecurity 3, installed it seamlessly with Nginx, and implemented the OWASP CRS on an Ubuntu Linux system, establishing a sturdy, open-source firewall for our server. This integration not only fortifies our defense against various web-based attacks but also significantly enhances the security of our web applications, ensuring the safekeeping of our operations and data. Each stage of this process was crucial, from prerequisite setup and ModSecurity installation to Nginx configuration and OWASP CRS implementation. We also developed proficiency in managing ModSecurity-generated logs and optimizing their sizes for peak performance while securing our specific Nginx configuration by deactivating automatic updates. This comprehensive and meticulous approach was indispensable in achieving the highest level of security for our setup.