Recommended Services
Supported Scripts
Checklist of ModSecurity tuning steps in cPanel WHM: enable vendor, OWASP CRS, hit list, whitelist rule ID

ModSecurity is the web application firewall built into cPanel/WHM, and it stops a huge amount of attack traffic before it ever reaches PHP. It also has a reputation for breaking things — blocked logins, failed file uploads, page builders that won’t save. Both are true. The difference between a WAF that protects you and one that generates support tickets is tuning. This guide covers enabling ModSecurity in WHM, picking a rule set, reading the hit list, and whitelisting false positives properly.

What ModSecurity Does

ModSecurity inspects every HTTP request — URL, headers, cookies and POST body — against a rule set, and blocks anything matching a known attack pattern: SQL injection, cross-site scripting, path traversal, command injection, malicious file uploads. Because it runs at the web-server layer, it protects every site on the server regardless of CMS, and it catches attacks against plugins you haven’t patched yet. It is a safety net, not a substitute for updates.

Enabling ModSecurity in WHM

First make sure the Apache module is installed via WHM » Software » EasyApache 4 — the package is ea-apache24-mod_security2. From the shell:

yum install ea-apache24-mod_security2 -y
/scripts/restartsrv_httpd

Then open WHM » Security Center » ModSecurity Configuration. The two settings that matter most:

  • Rules Engine — set to On to block, or DetectionOnly to log without blocking. Always start new rule sets in DetectionOnly for a few days.
  • Audit Log — enable it so you can see why a request was blocked. Without it you are debugging blind.

Choosing a Rule Set

WHM ships a vendor system — WHM » Security Center » ModSecurity Vendors — that installs and auto-updates rule sets for you. Never hand-edit vendor rule files; updates will overwrite them.

Rule setCostCharacter
OWASP ModSecurity Core Rule Set (CRS)FreeThe reference standard. Generic, well documented, tunable via paranoia levels.
Comodo WAFFree (registration)CMS-aware rules for WordPress/Joomla. Fewer false positives out of the box.
Imunify360 / Proactive DefensePaidCommercial rules with reputation feeds and automatic tuning.

Enable one primary rule set. Stacking OWASP CRS and Comodo together doubles your false positives for very little extra coverage.

Reading the Hit List Before You Change Anything

WHM » Security Center » ModSecurity Tools shows every rule that fired, grouped by rule ID, with the request that triggered it. This is where tuning starts. For each frequent hit, ask one question: was this a real attack, or a customer doing their job?

You can read the same data from the shell:

# The 20 most frequently triggered rule IDs
grep -oP '\[id "\K[0-9]+' /var/log/apache2/modsec_audit.log | sort | uniq -c | sort -rn | head -20

# Full detail for one rule ID
grep -B5 -A20 'id "949110"' /var/log/apache2/modsec_audit.log | less

A rule that fires thousands of times against one legitimate site is a false positive. A rule that fires once from fifty different IPs is doing its job.

Whitelisting a False Positive Correctly

ModSecurity Tools has a Disable Rule button, which is fine for a genuinely broken rule. But disabling a rule server-wide because one customer’s page builder tripped it removes that protection from every site you host. Prefer the narrowest fix that works.

Per-domain whitelist (recommended)

cPanel supports per-vhost Apache includes. Create the rule exception for one domain only:

mkdir -p /etc/apache2/conf.d/userdata/std/2_4/USERNAME/example.com
mkdir -p /etc/apache2/conf.d/userdata/ssl/2_4/USERNAME/example.com

cat > /etc/apache2/conf.d/userdata/std/2_4/USERNAME/example.com/modsec.conf <<'EOF'
<IfModule mod_security2.c>
    SecRuleRemoveById 949110 942100
</IfModule>
EOF

cp /etc/apache2/conf.d/userdata/std/2_4/USERNAME/example.com/modsec.conf \
   /etc/apache2/conf.d/userdata/ssl/2_4/USERNAME/example.com/modsec.conf

/scripts/ensure_vhost_includes --user=USERNAME
/scripts/restartsrv_httpd

Whitelist only one URL

Narrower still — disable the rule only where it actually misfires, such as the WordPress admin editor:

<IfModule mod_security2.c>
    SecRule REQUEST_URI "@beginsWith /wp-admin/admin-ajax.php" \
        "id:1000001,phase:1,pass,nolog,ctl:ruleRemoveById=942100"
</IfModule>

Use IDs in the 1000000–1999999 range for your own rules so they never collide with a vendor’s.

Paranoia Levels and Anomaly Scoring

OWASP CRS doesn’t block on a single match. Each rule adds to an anomaly score, and the request is blocked when the score crosses a threshold. Two dials control how aggressive this is:

  • Paranoia level 1–4 — level 1 is the sane default for shared hosting. Level 3+ will block legitimate traffic unless you tune extensively.
  • Inbound anomaly threshold — raise it from 5 to 7 or 10 to make blocking less trigger-happy while still logging everything.

Adjusting the threshold is almost always better than disabling rules, because you keep the detection and only change the verdict.

Testing That It Works

# Should return 403 with ModSecurity enabled
curl -I "https://example.com/?id=1%20OR%201=1--"

# Confirm the module is loaded
httpd -M 2>/dev/null | grep security

Then check the audit log to confirm the block was recorded with the rule ID you expected.

Conclusion

ModSecurity earns its place on a cPanel server, but only if you tune it. Install one vendor rule set, run it in DetectionOnly for a few days, read the hit list, and whitelist false positives per-domain or per-URL rather than server-wide. Raise the anomaly threshold instead of gutting rules. Done that way, the WAF blocks real attacks quietly and your customers never know it’s there.

Leave a Reply

Your email address will not be published. Required fields are marked *