ModSecurity is a widely-deployed open-source Web Application Firewall (WAF) that integrates directly with Apache as a module. Combined with the OWASP Core Rule Set (CRS), it provides protection against the most common web attack categories including SQL injection, cross-site scripting, and remote code execution. On RHEL 8, both the mod_security Apache module and the mod_security_crs rule package are available through the AppStream repository, simplifying installation. This tutorial covers installing and enabling ModSecurity with Apache, activating the OWASP CRS, testing the WAF, and tuning false positives.

Prerequisites

  • RHEL 8 server with a valid subscription or equivalent package mirror
  • Apache (httpd) installed and running — see the RHEL 8 Apache installation guide if needed
  • Root or sudo access
  • Ports 80 and/or 443 open via firewalld
  • A test web application or the default Apache welcome page to verify WAF behaviour

Step 1 — Install ModSecurity and the OWASP Core Rule Set

Both packages are available from the RHEL 8 AppStream repository. Install them with a single DNF command.

sudo dnf install -y mod_security mod_security_crs

DNF installs the Apache module (mod_security.so), the main configuration file at /etc/httpd/conf.d/mod_security.conf, and the CRS rule files under /etc/httpd/modsecurity.d/. The module is loaded automatically through the configuration file on the next Apache restart.

Step 2 — Enable Detection Mode in mod_security.conf

Before switching to blocking mode, run ModSecurity in detection-only mode to identify false positives without disrupting legitimate traffic.

sudo nano /etc/httpd/conf.d/mod_security.conf

Locate and set the following directive:

SecRuleEngine DetectionOnly

Once you have reviewed the audit log and are confident there are no false positives affecting production traffic, switch to prevention mode:

SecRuleEngine On

Additional recommended settings in the same file:

SecRequestBodyAccess On
SecResponseBodyAccess Off
SecAuditLog /var/log/httpd/modsec_audit.log
SecAuditLogParts ABIJDEFHZ
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"

Step 3 — Load the OWASP Core Rule Set

The OWASP CRS rules ship as individual configuration files. Verify the include directive in mod_security.conf is present and uncommented so that all CRS rule files are loaded.

grep -i "modsecurity.d" /etc/httpd/conf.d/mod_security.conf

You should see an IncludeOptional line pointing to /etc/httpd/modsecurity.d/*.conf. If it is missing, add it manually:

IncludeOptional /etc/httpd/modsecurity.d/*.conf
IncludeOptional /etc/httpd/modsecurity.d/activated_rules/*.conf

Restart Apache to apply the changes:

sudo systemctl restart httpd

Step 4 — Test the WAF with a Simulated Attack

Send a request that contains a common SQL injection pattern to verify ModSecurity detects it. Use curl from the server or a remote machine.

curl -I "http://localhost/?id=1'+OR+'1'='1"
curl -I "http://localhost/?q=alert(1)"

In DetectionOnly mode these requests will return HTTP 200 but will be logged. In On mode they will be blocked and return HTTP 403. Review the audit log to confirm the matches:

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

Step 5 — Tune False Positives

Real applications often trigger CRS rules legitimately. Identify the rule ID from the audit log (field id in section H) and create a custom exclusion file.

sudo nano /etc/httpd/modsecurity.d/activated_rules/local_exclusions.conf

Disable a specific rule by its ID:

# Disable rule 942100 (SQL injection via libinjection) for the /api/ path
SecRule REQUEST_URI "@beginsWith /api/" 
    "id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=942100"

# Globally remove a rule that generates too many false positives
SecRuleRemoveById 920350

Reload Apache after each change:

sudo apachectl configtest && sudo systemctl reload httpd

Conclusion

You have installed ModSecurity and the OWASP Core Rule Set on RHEL 8, configured the audit log, tested the WAF against simulated SQL injection and XSS payloads, and learned how to suppress false positives using SecRuleRemoveById. Running in detection mode first is a best practice that prevents service disruption while you build confidence in the rule set. Once tuning is complete, enabling prevention mode with SecRuleEngine On provides a meaningful barrier against automated web attacks.

Next steps: How to Configure Nginx with ModSecurity WAF on RHEL 8, How to Install and Configure Caddy Web Server on RHEL 8, and How to Configure Nginx Rate Limiting and Connection Throttling on RHEL 8.