Most “WordPress security” content tells you to use strong passwords and call it done. That’s table stakes. Real hardening goes further — disabling the dashboard’s file editor, rotating authentication salts, hiding wp-admin from automated scanners, locking down XML-RPC, and using PHP-level hardening. None of these take long; together they shrink your attack surface dramatically.
Things you should already have done
- Strong unique password for the admin account.
- 2FA on the WordPress admin login (plugins like Wordfence or Two-Factor).
- WordPress core, themes, plugins all updated.
- HTTPS forced site-wide.
- JetBackup or equivalent for restore points.
If you’re missing any of those, do them first. This guide covers the next layer.
Disable file editing from dashboard
WordPress admin → Appearance → Theme File Editor lets admins edit theme/plugin PHP from inside the browser. Any account that gets compromised can drop malicious code instantly. Disable it:
Add to wp-config.php (above the “/* That’s all, stop editing!” comment):
define('DISALLOW_FILE_EDIT', true);
You can also disable plugin/theme install/update from dashboard (forcing changes via FTP only):
define('DISALLOW_FILE_MODS', true);
The latter is more restrictive — you’ll need to update plugins via FTP or WP-CLI. Use it on high-security sites; skip on hands-off-managed sites where dashboard updates matter.
Rotate authentication salts
wp-config.php contains eight cryptographic “salts” that secure WordPress sessions and cookies. If yours were generated long ago, rotate them:
- Visit https://api.wordpress.org/secret-key/1.1/salt/ in a browser.
- It returns 8 lines of fresh salts.
- Open wp-config.php in cPanel File Manager.
- Find the section starting with
AUTH_KEYthroughNONCE_SALT. - Replace ALL 8 lines with the new ones from the API.
- Save.
Effect: all current sessions invalidated (you’ll need to log in again). Any session tokens an attacker had stolen also become useless.
Rotate after any suspected compromise. Otherwise annually.
Disable or restrict XML-RPC
XML-RPC was WordPress’s pre-REST-API remote control endpoint. Modern apps mostly use the REST API (/wp-json/). XML-RPC remains enabled by default, and it’s a frequent brute-force target — attackers can try many passwords per request.
If you don’t actively use XML-RPC, disable it. Add to .htaccess:
<Files xmlrpc.php>
Order Allow,Deny
Deny from all
</Files>
Or via filter in functions.php:
add_filter('xmlrpc_enabled', '__return_false');
Test after — if any of your tools stop working (Jetpack uses XML-RPC for some features, older mobile apps), allowlist their IPs instead of fully disabling.
Hide / change wp-admin URL
Bots scan /wp-login.php and /wp-admin/ thousands of times daily. Moving these to non-default URLs cuts brute-force attempts dramatically — not because security through obscurity is real protection, but because automated scanners don’t know to look elsewhere.
Plugin: WPS Hide Login. Change /wp-admin/ to /your-secret-path/. Bots hitting /wp-admin/ now get a 404 instead of finding a login form.
Important: don’t pick obvious names like /admin/, /login/. Choose something non-guessable.
Caveat: this is obscurity, not security. Real attackers who target your specific site will still find the new URL. But you’ll block 95% of generic bots.
Limit login attempts
Default WordPress allows unlimited login attempts — perfect for brute-forcing. Limit them:
- Plugin: Limit Login Attempts Reloaded or Wordfence Login Security.
- Setting: 5 attempts in 20 minutes, then 24-hour lockout.
- Server-level: CSF/Imunify360 already enforce some limits — this layer adds WordPress-specific blocking.
Restrict access to wp-config.php and .htaccess
Add to .htaccess:
<Files wp-config.php>
order allow,deny
deny from all
</Files>
<Files .htaccess>
order allow,deny
deny from all
</Files>
These should never be accessible directly via browser anyway, but explicit denial closes off any misconfiguration.
Disable directory listing
Anyone browsing to /wp-content/uploads/2024/01/ shouldn’t see a directory listing of files. Add to .htaccess:
Options -Indexes
This is usually default on properly configured servers, but verify by browsing to a folder URL without an index file — should get 403 Forbidden, not a directory listing.
Disable PHP execution in uploads
Uploaded files should be images, PDFs, documents — never PHP. If an attacker manages to upload a PHP file through some vulnerability, you don’t want it executable. Add to wp-content/uploads/.htaccess:
<Files *.php>
deny from all
</Files>
Stops PHP execution in uploads folder even if a malicious file gets in.
Database table prefix
Default WordPress tables are named wp_users, wp_options, etc. Some SQL-injection attacks rely on the default wp_ prefix. Changing it:
- Set at install time — easiest.
- After install: edit wp-config.php
$table_prefix = 'wp_';to e.g.'wpx2k_', then rename all tables in phpMyAdmin to match. - Risky to change on production. Mainly relevant when setting up new sites.
File permission audit
Run periodically. Correct permissions:
- Folders: 755
- Files: 644
- wp-config.php: 600 (or 644)
- .htaccess: 644
Fix permissions via cPanel File Manager → select files → right-click → Permissions, or via SSH:
cd public_html
find . -type d -exec chmod 755 {} ;
find . -type f -exec chmod 644 {} ;
chmod 600 wp-config.php
Use a security plugin (but only one)
Pick one and stick with it:
- Wordfence — Most comprehensive, free with paid premium. Includes WAF, malware scan, login security.
- Sucuri Security — Lightweight, good integrity monitoring.
- iThemes Security (Solid Security) — Settings-driven, less resource-intensive than Wordfence.
Two security plugins active simultaneously can conflict and create false positives. Pick one.
Server-level layers (already in place on iWebVault)
- Imunify360 — Malware scanning, kernel-level IDS.
- CSF — Brute-force protection, firewall rules.
- PHP disable_functions — Blocks shell-execution from compromised PHP. See disable_functions guide.
- ModSecurity rules — Application-level filtering of common attacks.
These run automatically; nothing to configure. Your WordPress-level hardening complements them.
Common questions
“Do I need to do all of these?” No — pick based on threat model. DISALLOW_FILE_EDIT and limit login attempts are essentially free; do them. Hiding wp-admin is impactful for high-traffic sites; less so for personal blogs. Database prefix changes are rarely worth the risk on production.
“Won’t all this slow my site?” Hardening is essentially free performance-wise. Plugin-based hardening (Wordfence) has some overhead but typically negligible.
“What about reCAPTCHA?” Helps against form spam more than brute force. Useful but not critical for login security if you have limit-login-attempts in place.
“How often should I audit security?” Quarterly review: confirm hardening still in place after WordPress updates, run a Wordfence scan, check for unused plugins/themes to delete.
What’s next
- If already compromised: Malware cleanup.
- PHP-level hardening: disable_functions.
- Backups for recovery: JetBackup.
None of these measures alone stops a determined attacker, but each one closes off automated attack paths that account for the overwhelming majority of WordPress compromises. Twenty minutes of hardening prevents most of what would otherwise turn into a malware cleanup project.
Was this helpful?
Thanks for your feedback!