Back to scan results
What this check probes
HEAD/GET on the standard admin paths:
- WordPress —
/wp-login.php, /wp-admin/, /xmlrpc.php.
- Joomla —
/administrator/.
- Drupal —
/user/login, /?q=user/login.
- Magento —
/admin/, /index.php/admin/.
- Generic —
/admin, /admin.php, /administrator, /login, /signin, /portal, /dashboard, /cms, /backend.
- App-server —
/manager/html (Tomcat), /host-manager/html, /jenkins/login.
For each response we look at the status (200), content type (HTML), and the body for form fields with names like user, username, password — distinguishing a real login form from a 404 page that happens to return 200.
Why this matters for PCI DSS
An exposed login page is the funnel for several attack types:
- Credential stuffing — botnets try usernames + passwords from previous breaches. WordPress sites see thousands of attempts a day from automated tools.
- Brute force — short passwords are tried exhaustively. Even 10 attempts/sec against a 6-character password completes in days.
- Username enumeration — many platforms reveal whether the username exists via different error messages or response timing.
- CVE exploitation — if the panel itself is unpatched (e.g., a critical WordPress core CVE), the attacker doesn't need credentials.
PCI DSS 4.0 Requirement 8.3.1 requires strong authentication. Requirement 8.3.6 requires lockout after 10 invalid attempts. Requirement 8.4.2 requires multi-factor authentication for all administrative access. Requirement 7.2 requires need-to-know access.
How to fix it
In rough order of effectiveness:
- Restrict by IP at the web server. Only your office, admin homes, or VPN range can reach the URL.
- Enforce MFA for every admin account. Mandatory, not optional. TOTP via Google Authenticator / Authy is free and effective.
- Rate limit at the proxy or with a plugin (Wordfence, Limit Login Attempts Reloaded, fail2ban). Lockout after 5–10 failed attempts for 15 minutes minimum.
- CAPTCHA on the login form to break automated stuffers.
- Rename the URL — security through obscurity, but reduces drive-by hits dramatically. WordPress: WPS Hide Login plugin.
nginx IP allow-list (WordPress example):
location ~ ^/(wp-login\.php|wp-admin/) {
allow 203.0.113.10;
allow 198.51.100.42;
deny all;
# then the normal PHP handler:
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
location = /xmlrpc.php { deny all; }
Apache (.htaccess in /wp-admin/):
<Files wp-login.php>
Require ip 203.0.113.10 198.51.100.42
</Files>
Cloudflare — Zone → Security → WAF → Custom rule: "URI Path contains /wp-login.php AND IP Source Address is not in {office, home}" → Block.
Disable XML-RPC on WordPress unless you actively need it (Jetpack, mobile app, IFTTT). It's an alternative login endpoint that bypasses many login-page protections.
Audit accounts — every admin account should be (a) for a current employee or contractor and (b) using a unique strong password (use a password manager). Disable defaults.