How to Install ModSecurity and OWASP CRS with Apache on Ubuntu (26.04, 24.04, 22.04)

ModSecurity is an open-source web application firewall (WAF) that monitors HTTP traffic and blocks common attack patterns. If you run WordPress, phpMyAdmin, custom PHP applications, or any web service exposed to the internet, ModSecurity with the OWASP Core Rule Set provides protection against SQL injection, cross-site scripting (XSS), and command injection attacks without requiring application code changes.

By the end of this guide, you will have ModSecurity configured with the OWASP CRS protecting your Apache server, real-time request filtering that blocks malicious payloads before they reach your application, and configurable rule sets you can tune to reduce false positives.

This guide covers Ubuntu 26.04, 24.04, and 22.04 LTS. All commands use Ubuntu’s default repositories; no third-party sources are required.

ModSecurity Version Availability by Ubuntu Release

Ubuntu’s default repositories include ModSecurity. No third-party repositories are required:

Ubuntu ReleaseModSecurity VersionCRS Package Version
Ubuntu 26.04 LTS2.9.x3.3.x
Ubuntu 24.04 LTS2.9.x3.3.x
Ubuntu 22.04 LTS2.9.x3.3.x

This guide also covers installing the latest OWASP CRS 4.x directly from GitHub, which provides more up-to-date security rules than the packaged versions.

Update Ubuntu System Packages

Before installing new software, update your package lists and upgrade existing packages to their latest versions:

sudo apt update && sudo apt upgrade

Install Apache HTTP Server

ModSecurity requires Apache as the underlying web server. If Apache is not already installed, install it with:

sudo apt install apache2

Verify Apache installed correctly and check its status:

sudo systemctl status apache2 --no-pager

Expected output shows Apache as active and running:

● apache2.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
     Active: active (running) since Sat 2026-01-25 07:53:41 UTC; 5min ago
   Main PID: 1234 (apache2)
...

For a detailed Apache setup, see our Apache installation guide for Ubuntu.

Install ModSecurity Apache Module

Install the ModSecurity module from Ubuntu’s default repositories:

sudo apt install libapache2-mod-security2

This package installs ModSecurity and automatically enables the security2 module in Apache. Verify the module is enabled:

sudo apachectl -M | grep security

Expected output:

 security2_module (shared)

If the module is not listed, enable it manually:

sudo a2enmod security2
sudo systemctl restart apache2

Configure ModSecurity

ModSecurity comes with a recommended configuration file that you need to activate. Copy the sample configuration to create the active configuration file:

sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

Open the configuration file for editing:

sudo nano /etc/modsecurity/modsecurity.conf

Enable Active Blocking Mode

By default, ModSecurity runs in DetectionOnly mode, which logs suspicious requests but does not block them. To actively block malicious traffic, change the rule engine setting near the top of the file (line 7):

Find this line:

SecRuleEngine DetectionOnly

Change it to:

SecRuleEngine On

Configure Audit Logging

The default SecAuditLogParts setting doesn’t log all useful information. Search for the SecAuditLogParts directive in the configuration file:

SecAuditLogParts ABDEFHIJZ

Change it to include response body and trailer information:

SecAuditLogParts ABCEFHJKZ

Save the file and exit the editor (Ctrl+O to save, Ctrl+X to exit in nano).

Restart Apache to apply the configuration changes:

sudo systemctl restart apache2

Install OWASP Core Rule Set (CRS)

ModSecurity provides the firewall engine, but it needs rules to detect attacks. The OWASP Core Rule Set (CRS) is the industry-standard rule set that protects against common web attacks including SQL injection, XSS, and remote code execution.

You have two installation options. The best choice depends on your Ubuntu version:

Ubuntu VersionRecommended CRS InstallationReason
Ubuntu 26.04 / 24.04Option 1: GitHub CRS 4.xModSecurity 2.9.6+ supports all CRS 4.x features
Ubuntu 22.04Option 2: Ubuntu RepositoriesModSecurity 2.9.5 is incompatible with CRS 4.x
  • Option 1: Latest CRS 4.x from GitHub – For Ubuntu 24.04 and 26.04 only. Provides the most current security rules.
  • Option 2: CRS from Ubuntu Repositories – Required for Ubuntu 22.04. Uses the packaged CRS version which is compatible with older ModSecurity versions.

Both CRS branches are actively maintained. The OWASP project releases security updates for CRS 3.x alongside CRS 4.x, so Ubuntu 22.04 users receive continued protection. The main difference is that CRS 4.x includes newer detection rules and features that require ModSecurity 2.9.6+.

Option 1: Install Latest OWASP CRS from GitHub (Ubuntu 24.04/26.04)

This option requires Ubuntu 24.04 or 26.04. Ubuntu 22.04 users must use Option 2 below because CRS 4.x uses the @within operator which requires ModSecurity 2.9.6 or newer.

This method automatically detects and downloads the latest CRS release from the official GitHub repository, providing access to CRS 4.x with the most current security rules.

First, ensure curl is installed for downloading:

sudo apt install curl -y

Create the CRS directory:

sudo mkdir -p /etc/apache2/modsec

Download and install the latest CRS release automatically:

CRS_VERSION=$(curl -s https://api.github.com/repos/coreruleset/coreruleset/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
echo "Downloading OWASP CRS $CRS_VERSION..."
curl -fSL "https://github.com/coreruleset/coreruleset/archive/refs/tags/${CRS_VERSION}.tar.gz" -o /tmp/crs.tar.gz
sudo tar xzf /tmp/crs.tar.gz -C /etc/apache2/modsec --strip-components=1
rm /tmp/crs.tar.gz
echo "OWASP CRS $CRS_VERSION installed to /etc/apache2/modsec/"

This script uses curl -fSL to download the archive (-f fails silently on HTTP errors, -S shows errors, -L follows redirects). The --strip-components=1 flag removes the top-level directory from the archive so files extract directly into /etc/apache2/modsec/.

Copy the example configuration file to create the active CRS configuration:

sudo cp /etc/apache2/modsec/crs-setup.conf.example /etc/apache2/modsec/crs-setup.conf

Copy the rule exclusion templates so you can add custom exclusions later:

sudo cp /etc/apache2/modsec/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example /etc/apache2/modsec/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
sudo cp /etc/apache2/modsec/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example /etc/apache2/modsec/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf

Now configure Apache to load the CRS rules. Edit the ModSecurity module configuration:

sudo nano /etc/apache2/mods-available/security2.conf

Replace the entire contents with:


    SecDataDir /var/cache/modsecurity

    # Include ModSecurity base configuration
    IncludeOptional /etc/modsecurity/*.conf

    # Include OWASP CRS configuration and rules
    Include /etc/apache2/modsec/crs-setup.conf
    Include /etc/apache2/modsec/rules/*.conf

On Ubuntu 26.04, remove the default CRS configuration to prevent rule ID conflicts:

sudo rm -f /etc/modsecurity/crs/crs-setup.conf 2>/dev/null

Test the Apache configuration for syntax errors:

sudo apachectl configtest

Expected output:

Syntax OK

Restart Apache to load the rules:

sudo systemctl restart apache2

Option 2: Install CRS from Ubuntu Repositories (Required for Ubuntu 22.04)

This method uses the CRS version packaged in Ubuntu’s repositories. It’s the required method for Ubuntu 22.04 (which has ModSecurity 2.9.5) and a simpler alternative for users who prefer automated package updates over manual GitHub downloads.

sudo apt install modsecurity-crs

This package automatically integrates with ModSecurity through the /usr/share/modsecurity-crs/*.load files that are already referenced in the default security2.conf.

Restart Apache to load the rules:

sudo systemctl restart apache2

Verify the CRS package is installed:

dpkg -l modsecurity-crs | tail -1

Expected output (version varies by Ubuntu release):

ii  modsecurity-crs  3.3.5-1  all  OWASP ModSecurity Core Rule Set

Verify ModSecurity Is Working

Test that ModSecurity correctly blocks malicious requests by sending a request that triggers a rule. Open a terminal and run:

curl -I "http://localhost/?exec=/bin/bash"

If ModSecurity is working correctly with the CRS, you should receive a 403 Forbidden response:

HTTP/1.1 403 Forbidden
Date: Sat, 25 Jan 2026 08:00:00 GMT
Server: Apache/2.4.65 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

If you receive a 200 OK response instead, verify that:

  • SecRuleEngine is set to On (not DetectionOnly)
  • The CRS rules are properly included in security2.conf
  • Apache was restarted after configuration changes

You can also test via your web browser by visiting https://yourdomain.com/?exec=/bin/bash (replace with your actual domain). A 403 Forbidden error page confirms ModSecurity is actively protecting your server.

Understanding OWASP CRS Configuration

The CRS provides extensive configuration options in the crs-setup.conf file. This section covers the most important settings you should understand.

Open the CRS configuration file:

sudo nano /etc/apache2/modsec/crs-setup.conf

Anomaly Scoring Mode

CRS operates in anomaly scoring mode by default. Instead of blocking on the first matched rule, each rule adds points to an “anomaly score.” When the score exceeds a threshold, the request is blocked. This approach reduces false positives by requiring multiple indicators before blocking.

The default thresholds are:

  • Inbound anomaly threshold: 5 points (blocks requests with 5+ points)
  • Outbound anomaly threshold: 4 points (blocks responses with 4+ points)

Higher thresholds allow more potentially suspicious traffic through but reduce false positives.

Paranoia Levels

CRS has four paranoia levels that control how aggressively rules detect threats:

  1. Paranoia Level 1 (default): Core rules with minimal false positives. Suitable for most websites.
  2. Paranoia Level 2: Enables additional rules. May require tuning for some applications.
  3. Paranoia Level 3: Strict rules intended for high-security applications. Expect false positives.
  4. Paranoia Level 4: Maximum security, high false positive rate. Only for specialized use cases.

Start with level 1 and only increase after monitoring your logs for a few weeks to understand your traffic patterns.

Handling False Positives

False positives (legitimate requests blocked incorrectly) are common when first deploying a WAF. The CRS provides several methods to handle them.

Enable Application-Specific Exclusions

CRS includes pre-built exclusions for popular applications. In crs-setup.conf, find and uncomment the exclusions for applications you use:

SecAction \
 "id:900130,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:tx.crs_exclusions_wordpress=1,\
  setvar:tx.crs_exclusions_phpmyadmin=1"

Available exclusions include: cpanel, dokuwiki, drupal, nextcloud, phpbb, phpmyadmin, wordpress, and xenforo.

Create Custom Rule Exclusions

For custom exclusions, edit the before-CRS exclusion file:

sudo nano /etc/apache2/modsec/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

Each exclusion rule needs a unique ID. Here are common exclusion patterns:

Disable rules for a specific URL path:

SecRule REQUEST_URI "@beginsWith /admin/api/" "id:1000,phase:1,pass,nolog,ctl:ruleRemoveById=941000-942999"

Whitelist an IP address from all rules:

SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" "id:1001,phase:1,allow,nolog,ctl:ruleEngine=off"

Whitelist a subnet:

SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8" "id:1002,phase:1,allow,nolog,ctl:ruleEngine=off"

Disable a specific rule globally:

SecRuleRemoveById 942100

To identify which rule is causing false positives, check the ModSecurity audit log:

sudo tail -f /var/log/apache2/modsec_audit.log

Look for lines containing the rule ID (e.g., [id "942100"]) that triggered the block.

Configure Log Rotation

ModSecurity logs can grow large quickly on busy servers. Configure log rotation to manage disk space:

sudo nano /etc/logrotate.d/modsecurity

Add the following configuration:

/var/log/apache2/modsec_audit.log {
    rotate 14
    daily
    missingok
    compress
    delaycompress
    notifempty
    create 640 root adm
}

This configuration keeps 14 days of logs, compresses old logs, and creates new log files with appropriate permissions.

Update OWASP CRS

If you installed CRS from GitHub, periodically update to get new rules and security fixes. The following script automates this process:

sudo nano /usr/local/bin/update-owasp-crs.sh

Add the following content:

#!/bin/bash
# OWASP CRS Update Script for ModSecurity on Apache

set -e

CRS_DIR="/etc/apache2/modsec"
BACKUP_DIR="/etc/apache2/modsec-backup-$(date +%Y%m%d)"

# Get current and latest versions
CURRENT_VERSION=""
if [ -f "$CRS_DIR/CHANGES.md" ]; then
    CURRENT_VERSION=$(grep -m1 "^## Version" "$CRS_DIR/CHANGES.md" | awk '{print $3}')
fi

LATEST_VERSION=$(curl -s https://api.github.com/repos/coreruleset/coreruleset/releases/latest | grep '"tag_name"' | cut -d'"' -f4)

echo "Current CRS version: ${CURRENT_VERSION:-Not installed}"
echo "Latest CRS version: $LATEST_VERSION"

if [ "$CURRENT_VERSION" = "${LATEST_VERSION#v}" ]; then
    echo "CRS is already up to date."
    exit 0
fi

echo "Updating to $LATEST_VERSION..."

# Backup current installation
if [ -d "$CRS_DIR" ]; then
    echo "Backing up current installation to $BACKUP_DIR"
    sudo cp -r "$CRS_DIR" "$BACKUP_DIR"
fi

# Preserve custom configuration
CUSTOM_SETUP=""
if [ -f "$CRS_DIR/crs-setup.conf" ]; then
    CUSTOM_SETUP=$(cat "$CRS_DIR/crs-setup.conf")
fi

# Download and extract new version
curl -fSL "https://github.com/coreruleset/coreruleset/archive/refs/tags/${LATEST_VERSION}.tar.gz" -o /tmp/crs.tar.gz
sudo rm -rf "$CRS_DIR"/*
sudo tar xzf /tmp/crs.tar.gz -C "$CRS_DIR" --strip-components=1
rm /tmp/crs.tar.gz

# Restore or create configuration
if [ -n "$CUSTOM_SETUP" ]; then
    echo "$CUSTOM_SETUP" | sudo tee "$CRS_DIR/crs-setup.conf" > /dev/null
    echo "Restored custom crs-setup.conf"
else
    sudo cp "$CRS_DIR/crs-setup.conf.example" "$CRS_DIR/crs-setup.conf"
fi

# Setup exclusion files
sudo cp "$CRS_DIR/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example" "$CRS_DIR/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf" 2>/dev/null || true
sudo cp "$CRS_DIR/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example" "$CRS_DIR/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf" 2>/dev/null || true

# Test Apache configuration
echo "Testing Apache configuration..."
if sudo apachectl configtest; then
    echo "Configuration test passed. Reloading Apache..."
    sudo systemctl reload apache2
    echo "CRS updated successfully to $LATEST_VERSION"
else
    echo "Configuration test failed! Restoring backup..."
    sudo rm -rf "$CRS_DIR"/*
    sudo cp -r "$BACKUP_DIR"/* "$CRS_DIR"/
    echo "Backup restored. Please check the error above."
    exit 1
fi

Make the script executable:

sudo chmod +x /usr/local/bin/update-owasp-crs.sh

Run the script to update CRS:

sudo /usr/local/bin/update-owasp-crs.sh

Expected output when an update is available:

Current CRS version: v4.22.0
Latest CRS version:  v4.23.0
Updating to v4.23.0...
Backing up current installation to /etc/apache2/modsec-backup-20260125
Configuration test passed. Reloading Apache...
CRS updated successfully to v4.23.0

If already up to date:

Current CRS version: v4.22.0
Latest CRS version:  v4.22.0
CRS is already up to date (v4.22.0)

Run this script periodically (monthly is usually sufficient) to keep your rules current with the latest security updates.

Troubleshooting

Apache Fails to Start After Configuration Changes

If Apache fails to start, check the configuration syntax:

sudo apachectl configtest

Common errors include:

  • Duplicate rule IDs: If you see “Found another rule with the same id”, remove conflicting CRS configurations (e.g., /etc/modsecurity/crs/crs-setup.conf on Ubuntu 26.04)
  • Missing include files: Verify the paths in security2.conf point to existing files
  • Syntax errors in exclusion rules: Each custom rule needs a unique id: value

ModSecurity Not Blocking Attacks

If ModSecurity doesn’t block test attacks:

  1. Verify SecRuleEngine is set to On in /etc/modsecurity/modsecurity.conf
  2. Check that CRS rules are being loaded: sudo apachectl -t -D DUMP_INCLUDES | grep -i modsec
  3. Review the error log for issues: sudo tail /var/log/apache2/error.log
  4. Ensure Apache was restarted after changes: sudo systemctl restart apache2

Legitimate Requests Being Blocked

To identify why a request was blocked:

sudo grep "$(date +%d/%b/%Y)" /var/log/apache2/modsec_audit.log | grep -A 10 "403"

Look for the [id "XXXXXX"] pattern to identify the blocking rule, then create an exclusion as described in the false positives section.

High Server Load After Enabling ModSecurity

ModSecurity adds processing overhead. If you notice performance issues:

  • Reduce the paranoia level to 1 if it’s higher
  • Disable response body scanning in modsecurity.conf: SecResponseBodyAccess Off
  • Limit which file types are scanned by configuring SecRequestBodyLimit and SecResponseBodyLimit

Remove ModSecurity

If you need to remove ModSecurity from your system, follow these steps.

First, disable the ModSecurity module:

sudo a2dismod security2
sudo systemctl restart apache2

Remove the ModSecurity packages:

sudo apt remove --purge libapache2-mod-security2 modsecurity-crs

Remove configuration files and CRS rules:

The following commands permanently delete all ModSecurity configuration files and OWASP CRS rules. If you have custom rule exclusions you want to preserve, back them up first with sudo cp -r /etc/apache2/modsec ~/modsec-backup.

sudo rm -rf /etc/modsecurity
sudo rm -rf /etc/apache2/modsec
sudo rm -f /etc/logrotate.d/modsecurity
sudo rm -f /usr/local/bin/update-owasp-crs.sh

Clean up unused dependencies:

sudo apt autoremove

Verify ModSecurity is removed:

sudo apachectl -M | grep security

This command should return no output if ModSecurity was successfully removed.

Additional Security Recommendations

ModSecurity with CRS provides application-layer protection. For comprehensive server security, consider implementing additional measures:

  • Firewall: Configure UFW to restrict network access. See our UFW firewall guide for Ubuntu.
  • Intrusion prevention: Use Fail2Ban to block repeated attack attempts. See our Fail2Ban installation guide.
  • SSL/TLS: Enable HTTPS with a valid certificate from Let’s Encrypt
  • Regular updates: Keep your system and CRS rules updated to protect against new vulnerabilities

Frequently Asked Questions

What is the difference between ModSecurity 2 and ModSecurity 3?

ModSecurity 2 (mod_security2) is an Apache module that runs directly inside Apache. ModSecurity 3 (libmodsecurity) is a standalone library that works with any web server through connectors. Ubuntu’s repositories provide ModSecurity 2 for Apache. If you use Nginx, you need ModSecurity 3 with the Nginx connector, which requires a different installation process.

Can I use ModSecurity with Nginx instead of Apache?

Yes, but it requires a different setup. Nginx uses ModSecurity 3 (libmodsecurity) with the ModSecurity-nginx connector module. This guide covers only Apache with ModSecurity 2. For Nginx, you typically need to compile the connector module from source, as it is not available in Ubuntu’s default repositories.

Does ModSecurity significantly affect website performance?

ModSecurity adds processing overhead because it inspects every HTTP request and response. For most websites, the impact is minimal (typically a few milliseconds per request). High-traffic sites may notice increased CPU usage. You can reduce overhead by disabling rules you don’t need, using anomaly scoring mode instead of immediate blocking, and tuning the paranoia level to match your security requirements.

Conclusion

You now have ModSecurity with OWASP CRS protecting your Apache server on Ubuntu. The web application firewall monitors all HTTP traffic and blocks common attack patterns including SQL injection, XSS, and command injection attempts. Regularly update your CRS rules using the provided update script, monitor your audit logs for false positives, and tune the rule exclusions to match your application’s needs.

Leave a Comment

Let us know you are human: