Common WordPress exposures and how to fix them
Most WordPress problems an outsider can see come from defaults and leftovers, not from exotic attacks. Here are the usual ones, how to check each on your own site and how to close it.
Why WordPress sites show so much
WordPress is popular and well documented, so automated tools know exactly which addresses to request on every WordPress site. Many of those addresses answer by default. That is not a vulnerability in itself, but it hands attackers a head start: usernames, versions and sometimes files that should never be public.
The sections below go roughly from the most harmful exposure to the least. Each says how to check your site and how to fix it. Replace your-site.example with your own address.
Exposed backups and config copies
A copy of wp-config.php with a .bak, .old, .save or ~ ending is not run by PHP. The web server sends it as plain text, with the database password and the secret keys inside. The same goes for backup.zip or dump.sql left in the web root.
Check: open https://your-site.example/wp-config.php.bak and similar names; anything other than 404 or 403 needs attention. Better still, look at the web root in the file manager of your hosting panel.
Fix: move backups out of the web root and block these extensions in the web server. Then change the database password and replace the WordPress keys and salts, because you cannot know who downloaded the file.
A public debug.log
When WP_DEBUG_LOG is on, WordPress writes errors to wp-content/debug.log by default. On many servers anyone can download that file. It can contain file paths, database queries and sometimes tokens or passwords from error messages.
Check: open https://your-site.example/wp-content/debug.log.
Fix: turn logging off on the live site (define('WP_DEBUG_LOG', false); in wp-config.php) or point it to a path outside the web root, block *.log files in wp-content, and change any secret that appears in the old log. The WordPress handbook advises using debug tools on local or staging copies, not on a production site.
xmlrpc.php
xmlrpc.php is an older remote API. The WordPress handbook calls it a frequent brute-force target, especially through the system.multicall method, which lets one request carry many login attempts.
Check: open https://your-site.example/xmlrpc.php. The message “XML-RPC server accepts POST requests only.” means it is enabled.
Fix: if you do not use it, block it in the web server or with a security plugin. Jetpack and the WordPress mobile apps rely on it; if you need it, rate-limit it and protect it with firewall rules.
User enumeration
On many WordPress sites /?author=1 redirects to /author/<name>/. That name is the author’s URL slug, which by default is derived from the login name. The REST API endpoint /wp-json/wp/v2/users can also list authors with their slugs.
Usernames are not secret by design, but knowing them leaves an attacker only the password to guess.
Fix: block ?author=N requests with a redirect rule or a security plugin, restrict the users endpoint for visitors who are not logged in, make admin logins differ from public display names, and turn on two-factor authentication and login rate limits.
Version leaks
WordPress adds a generator tag such as <meta name="generator" content="WordPress 6.x"> to pages, and every install ships readme.html and license.txt. Plugins ship readme.txt files whose “Stable tag” line usually names the plugin version, and asset links often end with ?ver= and a version number.
Hiding versions is worth doing, but it is cosmetic. The WordPress handbook calls security through obscurity “an unsound primary strategy”: hide the numbers, but rely on updates.
Fix: remove the generator tag (add_filter('the_generator', '__return_empty_string'); in a child theme or a small plugin), and block readme.html, license.txt and plugin readme.txt files in the web server, because WordPress restores the core files with every update.
Outdated core, plugins and themes
This is the exposure that matters most. Flaws in old plugins and themes are published, and anyone, including automated tools, can look them up for the versions your site shows.
- Update core, plugins and themes after a backup, and keep automatic minor core updates on.
- Delete plugins and themes you do not use instead of only deactivating them.
- Replace plugins that are no longer maintained.
- Keep PHP on a supported branch as well; here is how to check your PHP version.
What ZNIMOK detects on WordPress
When the check recognizes WordPress, it makes ordinary GET requests and reads the answers:
| Exposure | What the check requests or reads |
|---|---|
| Config copies | Common names such as wp-config.php.bak, .old, .save and ~, and whether the answer looks like a WordPress config file |
| Backups and dumps | Common names in the site root such as backup.zip, backup.sql and dump.sql |
| debug.log | /wp-content/debug.log, and whether it contains log entries |
| xmlrpc.php | /xmlrpc.php with a normal GET request |
| Author enumeration | /?author=1, and whether it leads to an author page |
| WordPress version | The generator tag on the homepage and /readme.html |
| Plugins | Plugin names and ?ver= values in homepage asset links, and the public readme.txt of five common plugins |
| Known issues | Detected versions compared with public vulnerability data and WordPress branch security releases |
The check does not try passwords, does not send XML-RPC calls and does not query the REST API user list. A detected version is a reason to check, not proof that the site is vulnerable. Run the WordPress security check to see which of these your site shows.
Questions
Is it safe to block xmlrpc.php?
For most sites, yes. First check whether you use Jetpack, the WordPress mobile app or a service that publishes posts remotely, because they need it.
Does hiding the WordPress version make my site secure?
No. It removes one easy clue. The site is as safe as the code it runs, so updates matter far more.
Is a public wp-login.php a problem?
A reachable login page is normal for WordPress. Protect it with strong passwords, two-factor authentication and login rate limits instead of relying on hiding it.
Sources
- WordPress handbook: Brute Force Attacks developer.wordpress.org
- WordPress handbook: Debugging in WordPress developer.wordpress.org
- WordPress handbook: Hardening WordPress developer.wordpress.org
- WordPress REST API reference: Users developer.wordpress.org