Hardening Your WordPress Database Security
Your WordPress database contains all your site data. Learn how to secure it against SQL injection, unauthorized access, and data theft.
Why Database Security Matters
Your WordPress database stores everything: posts, pages, comments, user information, settings, and plugin data. A compromised database means complete site compromise. Attackers target databases for user credentials, personal information, and to inject malicious content.
Change Default Table Prefix
Why Change the Prefix
WordPress uses "wp_" as the default table prefix. Attackers know this and craft SQL injection attacks targeting standard table names like wp_users.
Changing on New Installations
During installation, set a unique prefix:
$table_prefix = 'xyz123_';
Changing on Existing Sites
- Create complete backup
- Update wp-config.php prefix
- Rename tables in database
- Update prefix references in options and usermeta tables
Secure Database Credentials
Strong Password
Generate a complex database password:
- At least 20 characters
- Mix of all character types
- Randomly generated
- Unique to this database
Unique Database User
Create a dedicated MySQL user for WordPress instead of using root or a shared user.
Limit User Privileges
Grant only necessary permissions:
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX
ON wordpress_db.*
TO 'wp_user'@'localhost';
Avoid GRANT, FILE, and SUPER privileges.
Secure Database Connections
Local Connections Only
Restrict database access to localhost when possible:
define('DB_HOST', 'localhost');
Remote Database Security
If using remote database:
- Use SSL/TLS connections
- Restrict to specific IP addresses
- Use SSH tunnel when possible
Firewall Rules
Block external MySQL connections:
# Only allow local MySQL connections
iptables -A INPUT -p tcp --dport 3306 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP
SQL Injection Prevention
Use Prepared Statements
Always use WordPress's prepare method:
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$wpdb->posts} WHERE post_author = %d",
$user_id
)
);
Validate All Input
Sanitize data before database operations:
- sanitize_text_field()
- absint()
- sanitize_email()
- esc_sql() (prefer prepare)
Web Application Firewall
WAF rules can block SQL injection attempts before they reach your application.
Database Encryption
Encrypt Sensitive Data
Encrypt sensitive fields before storing:
// Store encrypted
$encrypted = openssl_encrypt($data, 'AES-256-CBC', $key, 0, $iv);
update_user_meta($user_id, 'sensitive_data', base64_encode($encrypted));
// Retrieve and decrypt
$encrypted = base64_decode(get_user_meta($user_id, 'sensitive_data', true));
$data = openssl_decrypt($encrypted, 'AES-256-CBC', $key, 0, $iv);
At-Rest Encryption
Enable MySQL encryption for data at rest if your hosting supports it.
Regular Maintenance
Optimize Tables
Regular optimization improves performance and removes fragmentation:
OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options;
Remove Orphaned Data
Clean up orphaned metadata:
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;
Limit Revisions
Reduce stored revisions:
define('WP_POST_REVISIONS', 5);
Database Backups
Automated Backups
Schedule regular database backups:
mysqldump -u user -p database > backup.sql
Secure Backup Storage
- Encrypt backup files
- Store off-server
- Test restoration regularly
Monitoring and Auditing
Query Logging
Enable MySQL general query log during security audits to identify suspicious queries.
Failed Query Monitoring
Monitor for database errors that may indicate attack attempts.
User Activity
Track database user connections and queries for anomalies.
Conclusion
Database security requires multiple layers: unique table prefixes, strong credentials, limited privileges, prepared statements, encryption, and regular maintenance. These measures protect your most valuable WordPress asset from compromise.
Written by Sarah Chen
WP Folder Shield Team