Key Takeaways
- Security plugins are helpful but not sufficient alone
- Server configuration provides foundational protection
- File permissions and ownership prevent unauthorized changes
- Keep everything updated—most attacks exploit known vulnerabilities
- Defense in depth: multiple overlapping security layers
Beyond Plugin Security
Security plugins are popular because they're easy to install. Add a plugin, configure some settings, and feel protected. But plugins operate within WordPress—they can't protect against attacks that bypass WordPress entirely or compromise the server beneath it.
Comprehensive WordPress security requires understanding the full stack: server, file system, database, WordPress configuration, and application. Each layer offers protection opportunities that plugins alone can't address.
Defense in Depth
No single security measure is foolproof. Effective security layers multiple protections, each covering different threats. If an attacker bypasses one layer, others remain. This redundancy is what "defense in depth" means in practice.
Server-Level Security
Web Server Configuration
Your web server (Apache, Nginx) can block many attacks before they reach WordPress:
Block Sensitive Files (Apache .htaccess)
# Block access to sensitive files
<FilesMatch "^(wp-config\.php|readme\.html|license\.txt|xmlrpc\.php)">
Require all denied
</FilesMatch>
# Block access to .htaccess itself
<Files .htaccess>
Require all denied
</Files>
# Block directory browsing
Options -Indexes
Nginx Equivalent
# Block sensitive files
location ~* ^/(wp-config\.php|readme\.html|license\.txt|xmlrpc\.php) {
deny all;
}
# Disable directory listing
autoindex off;
Disable XML-RPC
XML-RPC enables remote connections but is often exploited. If you don't need it:
# Disable XML-RPC in .htaccess
<Files xmlrpc.php>
Require all denied
</Files>
Secure HTTP Headers
# Security headers
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src 'self';"
Test Before Production
File System Security
File Permissions
Correct permissions prevent unauthorized modifications:
| Item | Permission | Notes |
|---|---|---|
| Directories | 755 (rwxr-xr-x) | Owner can write, others read/execute |
| Files | 644 (rw-r--r--) | Owner can write, others read only |
| wp-config.php | 600 (rw-------) | Only owner can read/write |
| .htaccess | 644 (rw-r--r--) | Web server needs read access |
File Ownership
Files should be owned by your user account, not the web server user:
# Set ownership (replace 'youruser' with actual user)
chown -R youruser:youruser /path/to/wordpress
# Set directory permissions
find /path/to/wordpress -type d -exec chmod 755 {} \;
# Set file permissions
find /path/to/wordpress -type f -exec chmod 644 {} \;
# Secure wp-config.php
chmod 600 /path/to/wordpress/wp-config.php
Prevent PHP Execution in Uploads
Block PHP execution in the uploads directory:
# In wp-content/uploads/.htaccess
<Files *.php>
deny from all
</Files>
WordPress Configuration
wp-config.php Hardening
// Disable file editing from admin
define( 'DISALLOW_FILE_EDIT', true );
// Disable plugin/theme installation from admin
define( 'DISALLOW_FILE_MODS', true );
// Force SSL for admin
define( 'FORCE_SSL_ADMIN', true );
// Limit post revisions
define( 'WP_POST_REVISIONS', 3 );
// Disable debug display in production
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', false );
// Use unique authentication keys and salts
// Generate at: https://api.wordpress.org/secret-key/1.1/salt/
Security Keys
Ensure you have strong, unique security keys. These encrypt session data:
- Generate fresh keys for every installation
- Rotate keys if you suspect compromise
- Never use defaults or share keys between sites
Database Security
- Use a unique database user per WordPress site
- Grant only necessary permissions (avoid GRANT ALL)
- Use a non-default table prefix (not wp_)
- Secure database credentials in wp-config.php
Move wp-config.php
WordPress allows wp-config.php to be moved one directory above the web root. This keeps database credentials outside the publicly accessible area—an extra layer of protection.
Disable Directory Indexing
Without proper configuration, visiting a directory URL shows file listings. This reveals your plugin and theme inventory to attackers. Always disable directory browsing.
Access Control
Login Security
- Enforce strong passwords
- Implement two-factor authentication
- Limit login attempts
- Consider changing the login URL
- Use application passwords for API access
User Management
- Follow principle of least privilege
- Remove unused accounts promptly
- Audit user roles regularly
- Don't use "admin" as a username
IP Restrictions
For admin access, consider IP whitelisting:
# Restrict wp-admin by IP
<Directory /path/to/wordpress/wp-admin>
Require ip 192.168.1.0/24
Require ip 10.0.0.0/8
</Directory>
Update Strategy
Updates are your most important security measure.
What to Update
- WordPress core
- All plugins (active and inactive)
- All themes (active and inactive)
- PHP version
- Web server software
- Operating system
Update Approach
-
Enable automatic updates for minor releases
Minor updates are usually security patches. Auto-updating reduces exposure time.
-
Test major updates on staging
Major versions may have breaking changes. Test before production.
-
Maintain current backups
Always have a restore point before applying updates.
-
Monitor after updates
Check site functionality after any update completes.
Managing Unused Items
- Delete inactive plugins—they're still attack vectors
- Delete unused themes (keep one default as fallback)
- Remove outdated files after migrations
Monitoring and Response
What to Monitor
- File integrity (changes to core files)
- Login attempts and failures
- New user creation
- Plugin and theme changes
- Unusual traffic patterns
Incident Response
Have a plan before you need it:
- How will you detect a compromise?
- Who responds and how?
- What's the communication plan?
- How do you restore from backup?
- What forensics do you preserve?
Log Everything
Layers of Protection
WordPress security isn't about finding the one perfect solution. It's about layering protections so attackers face multiple obstacles. Server hardening, file permissions, configuration security, access controls, updates, and monitoring each contribute to overall protection.
Start with the basics: updates and strong passwords. Then layer additional protections based on your risk level and technical capability. Security is an ongoing process, not a one-time configuration.
Frequently Asked Questions
Do I still need security plugins if I implement server-level hardening?
Can I do server-level hardening on shared hosting?
How often should I audit WordPress security?
What's the most important security measure for WordPress?
Need help securing your WordPress site?
I help organizations implement comprehensive WordPress security beyond basic plugins. Let's discuss your security requirements.