WordPress security hardening không phải là cài một plugin bảo mật rồi yên tâm. Với website production, hardening là một chuỗi kiểm soát: giảm bề mặt tấn công, giới hạn quyền, theo dõi thay đổi, có backup phục hồi được và kiểm tra định kỳ. Bài này đi theo góc nhìn sysadmin: dễ làm trong lab, nhưng đủ chặt để áp dụng cho site thật.
Bối cảnh lab: một VPS Ubuntu chạy Nginx/PHP-FPM/MariaDB, WordPress đặt tại /var/www/example.com/public, có SSH user triển khai riêng và domain đã bật HTTPS. Nếu anh dùng Apache, ý tưởng vẫn tương tự; chỉ khác phần cấu hình web server.
WordPress security hardening là gì?
WordPress security hardening là quá trình cấu hình WordPress, hệ điều hành, web server và quy trình vận hành để giảm khả năng bị khai thác. Nó không biến website thành “bất khả xâm phạm”, nhưng giúp:
- Chặn các lỗi phổ biến như brute force, upload shell, lộ file cấu hình.
- Giới hạn thiệt hại nếu một plugin hoặc tài khoản bị compromise.
- Phát hiện sớm thay đổi bất thường.
- Phục hồi nhanh bằng backup đã kiểm thử.
Checklist nhanh trước khi bắt đầu
- WordPress core, theme, plugin đang ở bản mới.
- Site có HTTPS hợp lệ.
- Không dùng tài khoản admin tên
admincho vận hành hằng ngày. - Có backup database và thư mục uploads trước khi chỉnh.
- Có quyền SSH hoặc ít nhất có quyền SFTP/hosting file manager.
1. Sao lưu trước khi hardening
Không chỉnh bảo mật trên production khi chưa có đường lui. Với server tự quản, có thể backup database và mã nguồn như sau:
mkdir -p /root/backups/wordpress
mysqldump -u wp_user -p wp_database | gzip > /root/backups/wordpress/db-$(date +%F).sql.gz
tar -czf /root/backups/wordpress/files-$(date +%F).tar.gz /var/www/example.com/public
ls -lh /root/backups/wordpress
Output mẫu:
-rw-r--r-- 1 root root 42M May 15 db-2026-05-15.sql.gz
-rw-r--r-- 1 root root 318M May 15 files-2026-05-15.tar.gz
Giải thích: mysqldump lưu database; tar lưu mã nguồn, theme, plugin và uploads. Sau khi backup xong, nên thử restore trên staging ít nhất một lần. Backup chưa từng restore thì chỉ là hy vọng.
2. Cập nhật core, plugin, theme bằng WP-CLI
Nếu server có WP-CLI, đây là cách kiểm tra trạng thái cập nhật rất nhanh:
cd /var/www/example.com/public
wp core check-update
wp plugin list --update=available
wp theme list --update=available
Khi đã có backup, cập nhật theo thứ tự core, plugin, theme:
wp core update
wp plugin update --all
wp theme update --all
wp cache flush
Với site có doanh thu, nên chạy trên staging trước. Một plugin lỗi có thể làm hỏng checkout, form liên hệ hoặc cache.
3. Gia cố file wp-config.php
wp-config.php chứa thông tin database và secret key, vì vậy cần hạn chế quyền đọc và tắt chỉnh sửa file từ dashboard:
define('DISALLOW_FILE_EDIT', true);
define('FORCE_SSL_ADMIN', true);
define('WP_DEBUG', false);
Đặt các dòng này trước phần /* That's all, stop editing! */. Sau đó kiểm tra quyền file:
chown www-data:www-data /var/www/example.com/public/wp-config.php
chmod 640 /var/www/example.com/public/wp-config.php
Nếu web server chạy bằng user khác www-data, hãy thay đúng user. Mục tiêu là WordPress đọc được file, nhưng user không liên quan không đọc được.
4. Thiết lập quyền file và thư mục an toàn
Quyền quá rộng như 777 là một trong các lỗi production phổ biến. Baseline thường dùng:
find /var/www/example.com/public -type d -exec chmod 755 {} \;
find /var/www/example.com/public -type f -exec chmod 644 {} \;
chmod 640 /var/www/example.com/public/wp-config.php
Nếu cần upload media, thư mục wp-content/uploads phải ghi được bởi PHP-FPM. Không cấp ghi toàn bộ source nếu không cần.
5. Chặn thực thi PHP trong uploads
Rất nhiều cuộc tấn công WordPress kết thúc bằng việc upload web shell vào wp-content/uploads. Với Nginx, có thể chặn PHP trong uploads:
location ~* /wp-content/uploads/.*\.php$ {
deny all;
}
Kiểm tra cấu hình và reload:
nginx -t
systemctl reload nginx
Với Apache, có thể dùng .htaccess trong uploads:
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
6. Bảo vệ đăng nhập và XML-RPC
Đường dẫn /wp-login.php và /xmlrpc.php thường bị brute force. Có ba lớp nên dùng:
- Bật 2FA cho tài khoản quản trị.
- Giới hạn login attempts hoặc dùng WAF/CDN.
- Tắt XML-RPC nếu không dùng Jetpack, mobile app hoặc tích hợp cũ.
Ví dụ Nginx chặn XML-RPC:
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
}
Nếu cần XML-RPC cho một dịch vụ cụ thể, không chặn toàn bộ; hãy allowlist IP hoặc dùng WAF rule.
7. Bật security headers cơ bản
Security headers giúp trình duyệt giảm rủi ro clickjacking, sniff MIME và downgrade HTTPS:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Riêng Content Security Policy cần test kỹ vì dễ làm hỏng theme, analytics hoặc trình soạn thảo. Đừng copy CSP cứng vào production nếu chưa kiểm thử.
8. Chọn plugin bảo mật theo nguyên tắc ít nhưng đúng
Plugin bảo mật hữu ích, nhưng không nên cài chồng nhiều plugin làm cùng một việc. Một bộ tối thiểu có thể gồm:
- Plugin 2FA cho tài khoản quản trị.
- Plugin audit log để biết ai đổi plugin, theme, user, option.
- Plugin backup có lịch lưu ra remote storage.
- WAF/CDN như Cloudflare nếu site public.
Luôn kiểm tra plugin có được cập nhật gần đây, số lượng active install, changelog và tương thích phiên bản WordPress hiện tại.
9. Monitoring và audit log
Hardening không kết thúc sau ngày triển khai. Cần theo dõi log:
tail -f /var/log/nginx/access.log /var/log/nginx/error.log
grep "wp-login.php" /var/log/nginx/access.log | tail -20
grep "xmlrpc.php" /var/log/nginx/access.log | tail -20
Dấu hiệu cần chú ý:
- Nhiều POST đến
wp-login.phptừ nhiều IP. - Request đến plugin cũ đã biết có CVE.
- File PHP lạ trong uploads.
- User admin mới được tạo nhưng không rõ nguồn gốc.
10. Troubleshooting lỗi thường gặp
Dashboard báo lỗi khi cập nhật plugin
Kiểm tra quyền ghi của wp-content và owner của file:
ls -ld wp-content wp-content/plugins
ps aux | grep php-fpm | head
Nếu PHP-FPM chạy bằng www-data nhưng file thuộc user khác và không có quyền ghi, cập nhật sẽ thất bại.
Ảnh upload được nhưng không hiển thị
Có thể rule chặn uploads quá rộng. Kiểm tra Nginx location và MIME type. Chỉ nên chặn file PHP trong uploads, không chặn jpg/png/webp.
Không đăng nhập được sau khi bật WAF
Kiểm tra rule rate limit hoặc bot fight mode. Allowlist IP quản trị nếu cần, nhưng đừng allowlist cả Internet. Nếu dùng Cloudflare, tham khảo tài liệu chính thức tại Cloudflare WAF documentation.
Checklist nghiệm thu sau hardening
- Site frontend tải bình thường, không lỗi console nghiêm trọng.
- Đăng nhập admin thành công qua HTTPS.
- Không chỉnh sửa được theme/plugin từ dashboard.
wp-config.phpkhông public qua trình duyệt.- File PHP trong uploads bị chặn thực thi.
- 2FA bật cho admin/editor quan trọng.
- Backup chạy theo lịch và đã thử restore.
- Log không còn spam XML-RPC hoặc đã có rule xử lý.
Lab cuối bài
Tạo một WordPress staging nhỏ, sau đó thực hiện:
- Backup database và source.
- Bật
DISALLOW_FILE_EDITvàFORCE_SSL_ADMIN. - Đặt quyền thư mục 755, file 644,
wp-config.php640. - Chặn PHP trong uploads.
- Bật 2FA cho tài khoản quản trị.
- Ghi lại trước/sau: quyền file, rule Nginx/Apache, kết quả đăng nhập, kết quả upload ảnh.
Đọc thêm tài liệu chính thống tại WordPress Hardening documentation và WordPress Backups documentation. Khi áp dụng đúng, WordPress security hardening giúp website khó bị khai thác hơn, dễ điều tra hơn và quan trọng nhất: phục hồi được khi có sự cố.
