Hardening WordPress cho SysAdmin: Bảo mật “tận gốc” từ Web Server đến Source Code

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Tiếng chuông báo động lúc 2 giờ sáng và bài học về log Nginx

Màn hình Terminal hiện liên hồi. Dashboard Netdata báo đỏ lừ: CPU con VPS 4 vCore chạy WordPress cho khách hàng vọt lên 100%, Load Average chạm ngưỡng 50. Mình gõ vội tail -f /var/log/nginx/access.log, một “cơn lũ” request POST vào xmlrpc.php hiện ra với tần suất 20 request mỗi giây. Server đang chịu một đợt Brute-force cực kỳ khủng khiếp.

Lúc đó mình mới thấm: cài plugin bảo mật như Wordfence chỉ là giải quyết phần ngọn. Khi request đã chạm đến tầng PHP, tài nguyên server đã bốc hơi rồi. Một SysAdmin khôn ngoan sẽ chặn đứng các cuộc tấn công này ngay từ “cửa ngõ” Web Server, trước khi chúng kịp làm phiền đến source code.

Dưới đây là quy trình Hardening một hệ thống WordPress đúng chuẩn production mình đã áp dụng để giữ cho server luôn ổn định dưới 5% CPU ngay cả khi bị scan.

Chiến thuật phòng thủ đa lớp (Defense in Depth)

Đừng bao giờ tin tưởng vào một lớp rào chắn duy nhất. Với WordPress, chúng ta sẽ thiết lập hệ thống phòng thủ theo thứ tự từ ngoài vào trong:

  • Tầng Web Server (Nginx): Đóng vai trò “vệ sĩ”, loại bỏ request xấu và giới hạn vùng nhạy cảm.
  • Tầng Hệ điều hành (OS): Siết chặt quyền hạn file, tuyệt đối không cho phép script lạ thực thi.
  • Tầng Source Code (PHP): Tinh chỉnh wp-config.php và xóa bỏ các dấu vết lộ phiên bản.
  • Tầng Database: Cô lập quyền hạn, chỉ cấp đủ quyền để WordPress vận hành.

Các bước Hardening chi tiết cho SysAdmin

1. Chặn đứng brute-force tại tầng Nginx

Hầu hết các tool scan tự động hiện nay đều nhắm vào xmlrpc.phpwp-login.php. Thay vì để PHP xử lý và tiêu tốn RAM, mình cấu hình Nginx từ chối thẳng thừng các request này.

# Chặn hoàn toàn truy cập vào xmlrpc.php để tiết kiệm tài nguyên
location = /xmlrpc.php {
    deny all;
    access_log off;
    log_not_found off;
}

# Chỉ cho phép IP văn phòng hoặc VPN truy cập vào trang quản trị
location ~ ^/(wp-admin|wp-login\.php) {
    allow 1.2.3.4; # Thay bằng IP tĩnh của bạn
    deny all;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}

Nếu bạn thường xuyên di chuyển và không có IP tĩnh, hãy sử dụng Basic Authentication (htpasswd). Cách này buộc hacker phải phá thêm một lớp mật khẩu nữa ở tầng web server trước khi thấy được form đăng nhập của WordPress.

2. Thiết lập phân quyền File System theo nguyên tắc tối thiểu

Để quyền 777 cho source code là sai lầm chết người. Nguyên tắc của mình rất đơn giản: Web server chỉ được quyền ghi vào thư mục /uploads, toàn bộ các file khác chỉ được phép đọc.

Thực thi các lệnh sau với user www-data để đưa server về trạng thái an toàn:

# Đặt chủ sở hữu cho toàn bộ project
chown -R www-data:www-data /var/www/html

# Thư mục để 755 (Owner có quyền ghi, Group và User khác chỉ được đọc/thực thi)
find /var/www/html -type d -exec chmod 755 {} \;

# File để 644 (Chỉ Owner được ghi)
find /var/www/html -type f -exec chmod 644 {} \;

# File cấu hình nhạy cảm nhất chỉ cho phép Owner đọc
chmod 600 /var/www/html/wp-config.php

Quan trọng nhất: Hãy chặn thực thi PHP trong thư mục uploads. Nếu hacker có lách được qua plugin nào đó để upload file shell, chúng cũng không thể kích hoạt được file đó.

# Cấu hình trong block server Nginx
location ~* ^/wp-content/uploads/.*\.php$ {
    deny all;
}

3. “Đóng băng” các tính năng nguy hiểm trong wp-config.php

File wp-config.php không chỉ để khai báo database. Bạn có thể biến nó thành một lớp khóa bảo vệ bằng cách thêm các dòng sau:

# Vô hiệu hóa trình sửa code trong Dashboard (chặn hacker sửa file khi chiếm được admin)
define( 'DISALLOW_FILE_EDIT', true );

# Ngăn cài đặt hoặc cập nhật plugin trực tiếp từ Web UI (chỉ dùng WP-CLI hoặc SFTP)
define( 'DISALLOW_FILE_MODS', true ); 

# Bắt buộc mã hóa mọi kết nối vào trang quản trị
define( 'FORCE_SSL_ADMIN', true );

# Giới hạn số bản lưu nháp để tránh làm phình Database
define( 'WP_POST_REVISIONS', 3 );

Mẹo nhỏ: Hãy làm mới các chuỗi Salt keys định kỳ. Việc này sẽ ngay lập tức vô hiệu hóa mọi cookie đăng nhập cũ, cực kỳ hữu ích nếu bạn nghi ngờ server bị rò rỉ session.

4. Xóa dấu vết (Security by Obscurity)

Đừng để hacker biết bạn đang dùng WordPress phiên bản cũ thông qua các thẻ meta generator. Trong file functions.php của theme, bạn hãy thêm:

remove_action('wp_head', 'wp_generator'); // Ẩn phiên bản WordPress
add_filter('login_errors', function(){ return 'Sai thông tin đăng nhập.'; }); // Không báo cụ thể sai user hay pass

Bên cạnh đó, hãy tắt thông tin định danh của Web Server để tránh bị khai thác các lỗ hổng theo version:

# Nginx: /etc/nginx/nginx.conf
server_tokens off;

# PHP: /etc/php/8.1/fpm/php.ini
expose_php = Off

5. Cô lập Database User

Dùng user root cho WordPress là thảm họa. Hãy tạo một user riêng biệt và chỉ cấp những quyền thực sự cần thiết. Một database bị chiếm quyền xóa (DROP) hoặc sửa cấu hình (ALTER) sẽ gây thiệt hại nặng nề hơn nhiều so với việc chỉ bị lấy dữ liệu.

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;

Lời kết

Bảo mật là một quá trình, không phải là một đích đến. Bằng cách thực hiện Hardening từ tầng Nginx đến Source Code, bạn đã loại bỏ được hơn 90% rủi ro từ các cuộc tấn công tự động. Hãy luôn duy trì thói quen backup định kỳ và cập nhật core WordPress ngay khi có bản vá. Khi hệ thống đã được gia cố vững chắc, những đêm 2 giờ sáng của bạn sẽ trở nên bình yên hơn rất nhiều.

Share: