Nền Tảng cho Nhà Quản Trị Hệ Thống
Bảo mật WordPress production không chỉ là cài một plugin security rồi để đó. Với website doanh nghiệp, WordPress thường là điểm tiếp xúc trực tiếp với Internet: có form đăng nhập, API, plugin bên thứ ba, theme, upload media, tài khoản biên tập viên và đôi khi còn kết nối CRM, email marketing hoặc thanh toán. Một lỗi nhỏ như plugin quá hạn, quyền file sai hoặc backup không kiểm tra khôi phục có thể biến thành sự cố thật.
Bài này là một hướng dẫn thực chiến để hardening WordPress trên môi trường production. Anh có thể dùng như checklist triển khai mới, checklist rà soát định kỳ hoặc runbook sau khi website vừa bị tấn công. Nội dung tập trung vào các bước có thể kiểm tra được: cập nhật, tài khoản, phân quyền, file permission, WAF, brute force protection, backup, logging, staging và nghiệm thu.
Trước khi hardening, cần hiểu rủi ro chính. Với WordPress public Internet, các cuộc tấn công phổ biến gồm:
/wp-login.php
Vì vậy, bảo mật WordPress production phải đi theo nhiều lớp: giảm bề mặt tấn công, cập nhật nhanh, hạn chế quyền, theo dõi log và luôn có đường khôi phục.
Giả sử website chạy theo mô hình phổ biến:
/var/www/example.com/public
Nếu anh dùng hosting quản trị sẵn, một số lệnh server-level có thể không chạy được. Khi đó hãy áp dụng phần tương đương trong control panel: file manager, backup, WAF, PHP version, cron và log viewer.
Cập nhật là việc quan trọng nhất, nhưng production không nên cập nhật bừa lúc cao điểm. Quy trình tối thiểu:
Với WP-CLI, có thể kiểm tra phiên bản như sau:
cd /var/www/example.com/public wp core version wp plugin list wp theme list
Output mẫu:
+----------------------+----------+-----------+---------+ | name | status | update | version | +----------------------+----------+-----------+---------+ | wordpress-seo | active | available | 24.8 | | litespeed-cache | active | none | 6.5.4 | +----------------------+----------+-----------+---------+
Plugin có update security nên được ưu tiên. Nếu plugin không còn duy trì, hãy lập kế hoạch thay thế thay vì chỉ “để đó vì vẫn chạy”.
Không nên dùng chung một tài khoản admin cho nhiều người. Checklist tài khoản:
admin
Dùng WP-CLI để liệt kê user:
wp user list --fields=ID,user_login,user_email,roles
Nếu cần hạ quyền một user:
wp user set-role editor_user editor
Việc này giảm thiệt hại khi một tài khoản biên tập bị lộ. Đây là nguyên tắc least privilege trong vận hành.
WordPress mặc định có endpoint đăng nhập rất dễ bị bot quét. Một cấu hình production nên có ít nhất ba lớp:
Nếu dùng Nginx, có thể rate limit cơ bản cho wp-login.php:
wp-login.php
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=5r/m; server { location = /wp-login.php { limit_req zone=wplogin burst=10 nodelay; include fastcgi_params; fastcgi_pass unix:/run/php/php8.2-fpm.sock; } }
Giải thích:
rate=5r/m
burst=10
Nếu dùng Cloudflare, nên tạo rule riêng cho /wp-login.php và /xmlrpc.php: Managed Challenge, rate limit hoặc chỉ allow IP quản trị nếu mô hình vận hành cho phép.
/xmlrpc.php
xmlrpc.php thường bị dùng để brute force hoặc DDoS amplification. Nếu website không dùng Jetpack, app mobile hoặc tích hợp cũ cần XML-RPC, nên chặn.
xmlrpc.php
Nginx:
location = /xmlrpc.php { deny all; access_log off; log_not_found off; }
Apache .htaccess:
.htaccess
Require all denied
Sau khi chặn, test:
curl -I https://example.com/xmlrpc.php
Kỳ vọng nhận 403 Forbidden hoặc bị WAF challenge, không phải 200 OK.
403 Forbidden
200 OK
Quyền file sai là nguyên nhân phổ biến khiến attacker ghi webshell sau khi khai thác một plugin. Mục tiêu là chỉ cho PHP/web server ghi nơi cần thiết, thường là wp-content/uploads, cache và một số thư mục plugin cụ thể.
wp-content/uploads
Baseline tham khảo:
cd /var/www/example.com/public find . -type d -exec chmod 755 {} \; find . -type f -exec chmod 644 {} \; chmod 600 wp-config.php
Owner nên tách rõ user deploy và user web server. Ví dụ:
sudo chown -R deploy:www-data /var/www/example.com/public sudo find /var/www/example.com/public -type d -exec chmod 755 {} \; sudo find /var/www/example.com/public -type f -exec chmod 644 {} \;
Lưu ý: đây là baseline. Một số plugin cache cần quyền ghi vào thư mục riêng. Đừng cấp 777 để “cho chạy được”; hãy xác định đúng thư mục cần ghi.
777
Thư mục upload không nên thực thi PHP. Đây là lớp bảo vệ quan trọng nếu attacker upload được file độc hại.
location ~* /wp-content/uploads/.*\.php$ { deny all; }
Apache, tạo file wp-content/uploads/.htaccess:
wp-content/uploads/.htaccess
Test bằng cách tạo file PHP giả trong môi trường staging, truy cập URL và xác nhận bị chặn. Không test kiểu này trên production nếu không kiểm soát chặt.
wp-config.php chứa credential database, salt và cấu hình quan trọng. Kiểm tra:
wp-config.php
ls -lah wp-config.php grep -E "AUTH_KEY|SECURE_AUTH_KEY|LOGGED_IN_KEY|NONCE_KEY" wp-config.php
Nếu nghi ngờ bị lộ phiên đăng nhập, thay salt bằng giá trị mới từ công cụ chính thức của WordPress:
Thay salt sẽ buộc user đăng nhập lại. Đây là thao tác hữu ích sau sự cố tài khoản hoặc nghi ngờ cookie/session bị lộ.
Không nên cho phép sửa theme/plugin trực tiếp trong wp-admin trên production. Thêm vào wp-config.php:
define('DISALLOW_FILE_EDIT', true);
Nếu muốn chặn cài/cập nhật từ dashboard và chỉ deploy qua pipeline, có thể dùng:
define('DISALLOW_FILE_MODS', true);
Tùy mô hình vận hành mà chọn. Với site nhỏ, DISALLOW_FILE_EDIT gần như luôn nên bật; DISALLOW_FILE_MODS cần cân nhắc vì nó ảnh hưởng update plugin/theme.
DISALLOW_FILE_EDIT
DISALLOW_FILE_MODS
Backup không được xem là hoàn thành nếu chưa từng restore thử. Một chiến lược tối thiểu:
Ví dụ backup database bằng WP-CLI:
mkdir -p /backup/example.com wp db export /backup/example.com/db-$(date +%F-%H%M).sql
Nén thư mục upload:
tar -czf /backup/example.com/uploads-$(date +%F).tar.gz wp-content/uploads
Kiểm tra file backup:
ls -lh /backup/example.com gzip -t /backup/example.com/uploads-2026-05-11.tar.gz
Quan trọng: không đặt backup trong webroot như /public/backup.zip. Nếu bắt buộc lưu tạm, phải chặn truy cập web và xóa ngay sau khi tải.
/public/backup.zip
Một site WordPress production nên theo dõi ít nhất:
Cấu hình debug an toàn trong wp-config.php khi cần troubleshooting:
define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); @ini_set('display_errors', 0);
Sau khi xử lý xong, nên tắt debug nếu không còn cần. Log debug có thể chứa thông tin nhạy cảm hoặc làm đầy disk.
Kiểm tra lỗi PHP gần nhất:
sudo journalctl -u php8.2-fpm --since "1 hour ago" --no-pager sudo tail -100 /var/log/nginx/error.log
Khi nghi ngờ bị tấn công, kiểm tra file PHP trong uploads:
find wp-content/uploads -type f -name "*.php" -print
Kiểm tra file mới thay đổi trong 2 ngày:
find . -type f -mtime -2 -print | sort
Tìm các pattern nguy hiểm thường gặp trong webshell:
grep -RIn --include="*.php" "eval(base64_decode\|shell_exec\|passthru\|assert(" wp-content 2>/dev/null | head -50
Lưu ý: grep chỉ là bước sàng lọc, có thể false positive hoặc bỏ sót mã độc obfuscation phức tạp. Với sự cố nghiêm trọng, nên restore từ bản sạch, thay toàn bộ credential và rà soát log truy cập.
WAF không thay thế cập nhật và hardening, nhưng giúp giảm đáng kể bot, exploit phổ biến và brute force. Checklist WAF:
.env
Tài liệu nên đọc thêm:
wp search-replace
Kết luận: bảo mật WordPress production là một quy trình vận hành liên tục, không phải một lần cài plugin. Khi anh kết hợp cập nhật có kiểm soát, phân quyền chặt, file permission đúng, WAF, backup có restore test và theo dõi log, website sẽ có khả năng chống chịu tốt hơn rất nhiều trước bot tự động lẫn sự cố vận hành thật.
Tôi là Hoàng Mạnh, người sáng lập blog SysadminSkills.com. Tôi viết về quản trị hệ thống, bảo mật máy chủ, DevOps và cách ứng dụng AI để tự động hóa công việc IT. Blog này là nơi tôi chia sẻ những gì đã học được từ thực tế – đơn giản, ngắn gọn và áp dụng được ngay. Xem tất cả bài viết của Mạnh Hoàng