# Lock Down WHM: 2FA, cPHulk and API Tokens for Secure Access

Source: https://srvscripts.com/guides/lock-down-whm-2fa-cphulk-api-tokens/
Updated: 2026-10-03
Publisher: srvScripts (https://srvscripts.com/)

Since April 2026 the cPanel security bulletins have arrived every two to three weeks, and several of them (CVE-2026-41940 in particular) gave an unauthenticated attacker root on WHM. Patching quickly is essential, but the servers that came through the year cleanly were the ones where WHM was not reachable from the open internet in the first place. The controls below reduce the attack surface of WHM itself; they do not replace timely updates, and you should still verify your build against our [CVE-to-build mapping](/guides/cpanel-cve-build-numbers-2026/).

In short: Enable two-factor authentication in WHM » Security Center and enrol root and every reseller, tighten cPHulk to around 5 failures in 5 minutes with firewall-level blocking, and use Host Access Control to allow whostmgrd and sshd only from…

**Short answer:** Enable two-factor authentication in WHM » Security Center and enrol root and every reseller, tighten cPHulk to around 5 failures in 5 minutes with firewall-level blocking, and use Host Access Control to allow `whostmgrd` and `sshd` only from your management addresses and deny `ALL` otherwise. Replace the root password in every integration with a scoped API token that has an expiry and an IP allowlist. None of this replaces patching, but it keeps WHM off the open internet where the 2026 zero-days were exploited.

## Enforce two-factor authentication for root and resellers

WHM’s 2FA uses TOTP and works with any authenticator app. Enable it under **WHM » Security Center » Two-Factor Authentication**, switch the feature on, and then enrol root immediately. Once root is enrolled, make it mandatory for resellers by leaving the feature enabled and auditing who has not configured it:

```
whmapi1 twofactorauth_get_user_configuration_status
```

Users without a configured secret appear with `is_enabled: 0`. Contact those resellers and give them a deadline; after that, the safest option is to suspend the reseller’s WHM access until they enrol.

Two caveats worth knowing. 2FA protects the login form, not API tokens or hash-based access, so tokens must be handled separately (below). And note that CVE-2026-41940 bypassed 2FA entirely because the flaw sat in the Basic Auth path before the second factor was evaluated. 2FA is a strong control against password reuse and phishing; it is not a control against code-execution bugs.

## Tune cPHulk rather than just enabling it

cPHulk Brute Force Protection is on by default, but the defaults are gentle. Open **WHM » Security Center » cPHulk Brute Force Protection » Configuration Settings** and consider:

- Lower the maximum failures per account from the default to around 5 within 5 minutes.

- Set the IP lockout to 15 failures and the block duration to at least 60 minutes.

- Enable “Block IP addresses at the firewall” if you run the cPanel CSF fork; this pushes cPHulk blocks into iptables rather than only into cPanel’s own auth layer.

- Add your office and monitoring IPs to the whitelist so you cannot lock yourselves out.

From the CLI:

```
whmapi1 set_cphulk_config_key key=max_failures value=5
whmapi1 set_cphulk_config_key key=lookback_period_min value=5
whmapi1 set_cphulk_config_key key=ip_brute_force_period_mins value=60
whmapi1 cphulk_whitelist_ips ips='203.0.113.10,198.51.100.0/24'
```

Check the live status and history with `whmapi1 cphulk_get_config` and `whmapi1 read_cphulk_records list_name=blocked`. A common pitfall is a shared office NAT: a single colleague with a stale saved password in a mail client will lock out the whole office in minutes, so always keep the whitelist current.

## Restrict WHM and SSH with Host Access Control

Host Access Control is cPanel’s front end to TCP wrappers, applied to cpsrvd (ports 2082/2083/2086/2087/2095/2096), sshd, ftpd and a few others. The rule set is evaluated top to bottom. A sensible policy for WHM is to allow a short list of management IPs and deny everything else, while leaving cPanel and webmail open because customers connect from anywhere.

Under **WHM » Security Center » Host Access Control**, add rules in this order:

- `whostmgrd` — `203.0.113.10, 198.51.100.0/24` — allow

- `whostmgrd` — `ALL` — deny

- `sshd` — your VPN range — allow

- `sshd` — `ALL` — deny

The file behind this UI is `/etc/hosts.allow`. Before saving a deny-all rule, open a second SSH session and keep it alive, then confirm you can still reach `https://hostname:2087` from an allowed address. If you cannot, edit `/etc/hosts.allow` from the surviving session. For SSH itself, pair this with the changes in [Hardening SSH on AlmaLinux 9](/guides/harden-ssh-almalinux-9/).

If your clients need WHM from arbitrary locations (resellers travelling, for example), a VPN or a bastion with a fixed egress IP is the cleaner design. Exposing 2087 to the world is what turned the 2026 zero-day into a ransomware campaign for many providers.

## Replace root passwords in scripts with scoped API tokens

Anything that automates against WHM (WHMCS, billing panels, monitoring, your own scripts) should use an API token, never the root password. Create tokens under **WHM » Development » Manage API Tokens** and grant only the privileges the caller needs. WHMCS provisioning, for example, needs account creation, suspension, package and password functions, but not “Everything”. Give each integration its own token so you can revoke one without touching the others, and set an expiry date.

```
whmapi1 api_token_create token_name='whmcs-prod' acl-1='create-acct' acl-2='suspend-acct' acl-3='kill-acct' acl-4='list-accts' acl-5='passwd' expires_at=1790000000
whmapi1 api_token_list
```

Tokens also support an IP allowlist (`whitelist_ip` in the create call). Use it. A token restricted to the billing server’s IP is worthless if leaked in a support ticket.

For account-level automation, cPanel users can create their own tokens in **cPanel » Security » Manage API Tokens**, which keeps reseller-level tokens out of customer scripts.

## Verify

Run through this after any change:

- `whmapi1 twofactorauth_get_user_configuration_status` shows root and all resellers as enabled.

- `curl -sk https://hostname:2087/` from a non-whitelisted IP is refused at the TCP wrapper level (connection closed without a login page).

- `whmapi1 api_token_list` shows no token with full privileges that does not have both an expiry and an IP allowlist.

- `grep -c 'FAILED LOGIN' /usr/local/cpanel/logs/login_log` over a day shows cPHulk is catching and blocking repeated attempts rather than letting them run.

Our [server security audit script](/scripts/server-security-audit/) checks all four of these on a schedule and reports drift. Review the report monthly and after every staff change, because the most common failure is not a technical one: it is a departed engineer’s token or whitelisted home IP that never got removed.

## Lock down WHM at a glance

**Official documentation:** [cPanel & WHM documentation](https://docs.cpanel.net/), [Linux man pages](https://man7.org/linux/man-pages/).

**Related guides:** [Incident response after a cPanel root-escalation CVE: rotating keys, hunting .sorry, auditing sessions](https://srvscripts.com/guides/cpanel-root-escalation-incident-response/) · [CSF after ConfigServer: which fork should you run in 2026 (cPanel, DirectAdmin, Aetherinox, Sentinel)?](https://srvscripts.com/guides/csf-fork-2026-after-configserver/) · [Using WP Toolkit Security Risk scores, Smart Update and Vulnerable Components](https://srvscripts.com/guides/wp-toolkit-security-risk-score/).

## Frequently asked questions

### Does WHM two-factor authentication protect API tokens too?

No. 2FA is checked only on the login form; API tokens and hash-based access bypass it by design, and CVE-2026-41940 bypassed it as well because the flaw sat before the second factor. Protect tokens with limited ACLs, an expiry and the `whitelist_ip` allowlist instead.

### How do I restrict WHM port 2087 to specific IP addresses?

Add rules in WHM » Security Center » Host Access Control: `whostmgrd` allow for your management addresses, then `whostmgrd` deny `ALL`. Keep a second SSH session open while saving, and test from an allowed address before closing it; the rules live in `/etc/hosts.allow` if you need to fix them by hand.

### Will cPHulk lock out my whole office from a shared NAT?

It can, because a single colleague with a stale password in a mail client generates repeated failures from the office’s one public IP. Whitelist your office and monitoring addresses with `whmapi1 cphulk_whitelist_ips` and keep that list current.
