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 Release | ModSecurity Version | CRS Package Version |
|---|---|---|
| Ubuntu 26.04 LTS | 2.9.x | 3.3.x |
| Ubuntu 24.04 LTS | 2.9.x | 3.3.x |
| Ubuntu 22.04 LTS | 2.9.x | 3.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 Version | Recommended CRS Installation | Reason |
|---|---|---|
| Ubuntu 26.04 / 24.04 | Option 1: GitHub CRS 4.x | ModSecurity 2.9.6+ supports all CRS 4.x features |
| Ubuntu 22.04 | Option 2: Ubuntu Repositories | ModSecurity 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
@withinoperator 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 -fSLto download the archive (-ffails silently on HTTP errors,-Sshows errors,-Lfollows redirects). The--strip-components=1flag 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:
SecRuleEngineis set toOn(notDetectionOnly)- 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:
- Paranoia Level 1 (default): Core rules with minimal false positives. Suitable for most websites.
- Paranoia Level 2: Enables additional rules. May require tuning for some applications.
- Paranoia Level 3: Strict rules intended for high-security applications. Expect false positives.
- 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.confon Ubuntu 26.04) - Missing include files: Verify the paths in
security2.confpoint 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:
- Verify
SecRuleEngineis set toOnin/etc/modsecurity/modsecurity.conf - Check that CRS rules are being loaded:
sudo apachectl -t -D DUMP_INCLUDES | grep -i modsec - Review the error log for issues:
sudo tail /var/log/apache2/error.log - 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
SecRequestBodyLimitandSecResponseBodyLimit
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
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.
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.
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.