Web
WordPress security: a 12-point checklist before the expertise
Updates, plugin audit, xmlrpc, disabling file editing, no PHP in uploads, admin accounts, 2FA, backups, WAF and checksums — with commands and settings.
· 11 min read

WordPress is a widely used site platform, and in Uzbekistan many corporate sites and portals run on it. Its core is well maintained, but the risk on a real site is usually not in the core: it is in outdated plugins, default features left open, extra administrators and backups nobody has tested.
In this post we have collected 12 points to check before submitting a WordPress site to the official cybersecurity expertise. For each one: why it matters, how to check it and how to fix it. Most commands run through WP-CLI.
Why WordPress needs special attention
Expertise scanners recognise WordPress immediately and run WordPress-specific checks: core and plugin versions, username enumeration, xmlrpc.php, readme.html, the uploads folder. These checks are automated and fast, so every default thing left open turns into a finding in the report.
The real compromise we cleaned recently started exactly this way: with one plugin that was never updated.
1. Core, plugins and themes are up to date
The most important point. See which plugins have updates:
wp core check-update
wp plugin list --update=available --fields=name,version,update_version
wp theme list --update=available
Update:
wp core update && wp core update-db
wp plugin update --all
wp theme update --all
Take a backup before updating production and, if possible, test on a staging copy first. The PHP version must also be supported and have its security fixes installed.
2. Plugin audit
Every plugin is extra code and extra attack surface. Review the list:
wp plugin list --fields=name,status,version
- Remove inactive plugins. A deactivated plugin's files stay on the server, and a vulnerability in them can still be exploited. Don't just deactivate — delete completely:
wp plugin delete <name>. - Replace abandoned plugins. If a plugin hasn't been updated for a long time or was pulled from the directory, find an alternative.
- Drop "nulled" (cracked premium) plugins. They are often distributed with a backdoor already built in.
- Check unfamiliar plugins. A plugin with a random name can be a sign of compromise.
3. xmlrpc.php is closed
xmlrpc.php is an old remote management interface. It is often used for password guessing: a single request can carry many login attempts. If no service uses it (for example, a mobile app or Jetpack), close it.
Check:
curl -s -X POST https://site.uz/xmlrpc.php \
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>'
If the response returns a list of methods, the interface is open. Closing it in nginx:
location = /xmlrpc.php { deny all; }
In Apache, .htaccess:
<Files xmlrpc.php>
Require all denied
</Files>
4. File editing from the admin panel is disabled
The WordPress admin panel can edit theme and plugin files directly. If an administrator account is taken over, that instantly becomes code execution on the server. Add to wp-config.php:
define('DISALLOW_FILE_EDIT', true);
A stricter option is DISALLOW_FILE_MODS: it also blocks installing and updating plugins from the admin panel. In that case updates have to go through WP-CLI or your deploy process — otherwise the site simply stops being updated.
define('DISALLOW_FILE_MODS', true);
5. PHP does not execute in uploads
wp-content/uploads is where users upload files. If an attacker can place a PHP file there and the server executes it, that is full control. Check:
find wp-content/uploads -type f -iname '*.php*'
The result should be empty. Then forbid PHP execution at the web server level. nginx:
location ~* ^/wp-content/uploads/.*\.(php|phtml|phar)$ {
deny all;
}
For Apache, wp-content/uploads/.htaccess:
<FilesMatch "\.(php|phtml|phar)$">
Require all denied
</FilesMatch>
More on uploads: file upload vulnerabilities.
6. Administrator accounts are in order
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
- Know who owns every administrator account. An unfamiliar one is checked immediately.
- Don't use guessable logins like
admin. - Staff who work with content need the
editororauthorrole — not administrator. - Remove accounts of people who have left.
Also check for username disclosure — the expertise records it separately:
curl -s https://site.uz/wp-json/wp/v2/users | head -c 300
curl -sI 'https://site.uz/?author=1' | grep -i location
If logins are visible, close the users endpoint for guests (in the theme's functions.php or a small must-use plugin):
add_filter('rest_endpoints', function ($endpoints) {
if (!is_user_logged_in()) {
unset($endpoints['/wp/v2/users']);
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
}
return $endpoints;
});
7. Login protection and 2FA
Two-factor authentication (2FA) should be enabled for administrators — reliable plugins exist for this. In addition:
- Limit login attempts (with a plugin or rate limiting at the web server level).
- Require strong passwords.
- Where possible, restrict access to
wp-login.phpandwp-adminby IP list.
Simple rate limiting for wp-login.php in nginx:
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=5r/m;
location = /wp-login.php {
limit_req zone=wplogin burst=5 nodelay;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
More detail: login protection.
8. wp-config.php and file permissions
wp-config.phpmust not be readable by other users:chmod 640 wp-config.php(or600if PHP runs as the file owner).- Folders
755, files644—777should not appear anywhere:
find . -type d -perm -o+w
find . -type f -perm -o+w
- Debug mode is off in production:
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
define('FORCE_SSL_ADMIN', true);
- Keys and salts are unique. If in doubt, run
wp config shuffle-salts.
On debug mode: debug mode and information disclosure.
9. Version and leftover files are hidden
readme.html, license.txt and the <meta name="generator"> tag reveal the WordPress version. Remove or block them:
rm -f readme.html license.txt wp-config-sample.php
remove_action('wp_head', 'wp_generator');
Also make sure no .zip, .sql, .bak files or .git folders are left in the web root:
find . -maxdepth 2 \( -name '*.zip' -o -name '*.sql' -o -name '*.bak' -o -name '.git' \)
An exposed backup archive is the whole site and database in one file.
10. Backups exist and restore has been tested
- Backups are automatic and regular: files and database.
- A copy is stored off the server — if the site is compromised, the backup must not be.
- Backup archives are not in the web root. Some backup plugins store archives inside
uploads— check whether they can be reached from a browser. - A restore has been tested at least once. A backup you cannot restore from is not a backup.
11. A WAF is enabled
A Web Application Firewall stops known attack patterns (SQL injection, requests to vulnerable plugin endpoints, scanners) before they reach the site. Options:
- Server level: ModSecurity with the OWASP Core Rule Set.
- A WAF at an external proxy or CDN.
- A firewall at the WordPress plugin level.
A WAF does not replace updates — it is an extra layer. But it helps in the gap between a vulnerability being published and a fix being available.
12. Checksums are verified
Check that core and plugin files match the official release:
wp core verify-checksums
wp plugin verify-checksums --all
These commands list modified or foreign files. The result should be clean. If a file doesn't match, take it seriously and find out why. It is worth running this check after every update and on a regular schedule.
On top of that, set up HTTPS and security headers: security headers: CSP and HSTS.
Short checklist
- Core, plugins, themes and PHP are on the latest versions.
- Inactive, abandoned and "nulled" plugins are removed.
xmlrpc.phpis closed (if not needed).DISALLOW_FILE_EDITis enabled.- There is no PHP in
uploads, and its execution is forbidden. - The administrator list is reviewed; usernames are not disclosed.
- 2FA and login rate limiting are enabled for administrators.
wp-config.phppermissions are restricted, debug is off, no777.readme.html, the generator meta tag, archives and.gitin the web root are removed.- Backups are off-server and restore is tested.
- A WAF is enabled.
wp core verify-checksumsandwp plugin verify-checksums --allare clean.
Summary
Preparing a WordPress site for the expertise is mostly a matter of discipline: update, remove what you don't need, close what is open by default, and verify the result. These 12 points don't take long, but they close a large share of the most common findings in expertise reports ahead of time.
Want to know how well your WordPress site matches this list? Request a security scan — the Claude AI agent and our specialist will review your site and server configuration, and we will help close the holes we find and prepare for the expertise.


