Chặn User Enumeration WordPress: Hướng Dẫn A-Z Đế Bảo Vệ Username Admin

Mình vừa xong ca rà soát website cho một khách hàng sau đợt lỗi Pods plugin CVSS 9.8 tuần trước. Điều đáng nói không phải là plugin lỗi, mà là log access: bot quét /?author=1 nhiều gấp 4 lần bình thường. Tức là trước khi khai thác lỗ hổng, attacker phải biết username admin của bạn đã. Đó chính là user enumeration — và hôm nay mình sẽ hướng dẫn bạn chặn nó từ A đến Z.

Nói ngắn gọn: user enumeration là khả năng kẻ xấu dò ra tên đăng nhập của bạn qua các “cửa hậu” quen thuộc của WordPress. Chặn được nó là bạn đã khóa bước đầu tiên của hầu hết cuộc tấn công brute-force.

User enumeration là gì và vì sao WordPress bị dò username dễ vậy?

User enumeration là kỹ thuật kẻ tấn công dùng để liệt kê username trên website của bạn. WordPress mặc định để lộ tên người dùng qua ba đường: tham số ?author=1 chuyển hướng sang URL chứa nicename, REST API endpoint /wp-json/wp/v2/users trả về danh sách user công khai, và lỗi đăng nhập khác nhau giữa “sai username” và “sai password”. Biết username rồi, brute-force chỉ còn đi nửa đường.

Kiểm tra website của bạn có đang lộ username không?

Bạn làm theo 3 bước sau là biết ngay site mình có bị lộ hay không. Mình khuyên bạn test cả 3 đường vì chặn một đường không có nghĩa là hết.

Bước 1: Test tham số author

Mở terminal và chạy:

curl -sI "https://yourdomain.com/?author=1" | grep -i location

Nếu kết quả trả về Location: /author/ten-admin/ là site bạn đang lộ. Nếu trả về trang chủ hoặc lỗi 404, đường này đã được chặn.

Bước 2: Test REST API users

Chạy tiếp:

curl -s "https://yourdomain.com/wp-json/wp/v2/users" | head -c 500

Nếu thấy JSON chứa "slug":"ten-admin", username của bạn đang bị lộ công khai. Đây là đường phổ biến nhất mà bot khai thác hiện nay.

Bước 3: Test thông báo lỗi đăng nhập

Vào /wp-login.php, gõ một username nguỵ tạo kèm mật khẩu sai. Nếu WordPress báo “Invalid username” thay vì “Invalid password”, bạn vừa xác nhận cho kẻ xấu username nào tồn tại. Lưu ý: bước này phải sửa bằng filter, đừng bỏ qua.

Cách chặn author scan trên Nginx và OpenLiteSpeed như thế nào?

Chặn ở tầng web server là cách nhanh và nhẹ nhất, trước khi request chạm tới PHP. Với Nginx hoặc OpenLiteSpeed, bạn thêm rule sau vào server block (OLS đặt trong Context hoặc rewrite rule tương ứng):

if ($args ~* "^author=.*") {
    return 403;
}
location ~ ^/wp-json/wp/v2/users {
    return 403;
}

Sau đó reload lại service:

sudo nginx -t && sudo systemctl reload nginx

Lưu ý: đừng return 301 về trang chủ — nhiều bạn hay làm vậy. Trả 301 giúp bot biết URL cũ hợp lệ và nó sẽ thử tiếp các biến thể. 403 thẳng thừng là tín hiệu “hết cửa” rẻ nhất về mặt crawl budget cho bạn.

Chặn REST API users endpoint bằng code trong theme có an toàn không?

Có, và đây là cách mình khuyên dùng nếu bạn không được sửa web server config (ví dụ đang dùng shared hosting). Thêm vào file functions.php của child theme hoặc một plugin snippet:

add_filter('rest_endpoints', function ($endpoints) {
    if (isset($endpoints['/wp/v2/users'])) {
        unset($endpoints['/wp/v2/users']);
    }
    if (isset($endpoints['/wp/v2/users/(?P<id>[\d]+)'])) {
        unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
    }
    return $endpoints;
});

Nhớ unset cả endpoint theo ID, vì nhiều bot giờ quét thẳng /wp-json/wp/v2/users/1 thay vì list toàn bộ. Nếu bạn dùng plugin như WPCode thì dán snippet này vào và đặt chạy trên whole site là xong.

Sửa thông báo lỗi wp-login.php ra sao cho đúng?

Bước này đơn giản hơn bạn nghĩ. Thêm filter sau để đồng nhất thông báo lỗi:

add_filter('login_errors', function () {
    return 'Thông tin đăng nhập không đúng.';
});

Một dòng, nhưng hiệu quả thật. Khi cả hai trường hợp sai username hay sai password đều ra cùng một câu, kẻ xấu không còn cơ sở phân biệt. Đồng thời, đây cũng là lúc bạn bật login limit — nếu host của bạn không có, plugin WP Limit Login Attempts hoặc mod_security rule đều được. Nếu chưa chắc host mình có hạn chế đăng nhập không, đọc lại bài hướng dẫn tự kiểm tra secure hosting mà mình viết tuần trước.

Nên đổi username “admin” thành gì và đổi bằng lệnh nào?

Câu trả lời: đừng dùng username dễ đoán như admin, administrator hay tên miền. Nếu đang bị kẹt với username cũ, bạn đổi bằng WP-CLI trong 30 giây, không cần cài plugin:

sudo -u www-data wp user update admin --user_login=thanh2ng \
  --path=/var/www/yourdomain.com/public_html

Nếu lệnh wp user update không cho đổi login name ở bản WP-CLI của bạn (một số bản cũ có vậy), cách chắc ăn là tạo user mới với vai trò Administrator, đăng xuất, đăng nhập bằng user mới rồi xóa user cũ:

sudo -u www-data wp user create tungle [email protected] --role=administrator --user_pass=MatKhauManh
sudo -u www-data wp user delete admin --reassign=tungle

Lưu ý: bước 2 trong danh sách này — reassign bài viết — là bước nhiều bạn hay quên, dẫn đến mất toàn bộ post của tác giả cũ. Đừng bỏ qua.

Có plugin nào làm hết mọi thứ trên không?

Có, và mình phải nói thẳng: nếu bạn không muốn đụng code, các plugin bảo mật như Wordfence, Solid Security hay Patchstack đều có toggle chặn user enumeration. Nhưng theo kinh nghiệm của mình, plugin là lớp thứ hai, không phải lớp một. Rule ở tầng Nginx/OLS chạy nhanh hơn và không phụ thuộc plugin có bị lỗi hay không. Sau đợt CVE liên tục từ miniOrange tới Elementor Pro gần đây, mình tin nguyên tắc “ít plugin nhất có thể” hơn bao giờ hết.

Troubleshooting: các lỗi hay gặp khi chặn user enumeration

Mình tổng hợp lại vài lỗi học viên của mình hay gặp, kèm cách xử:

  • Chặn /wp-json/wp/v2/users làm hỏng theme hoặc app mobile: một số theme headless gọi endpoint này để hiển thị tác giả. Cách xử: chỉ chặn với request không đăng nhập, hoặc expose field tối thiểu qua rest_user_query filter.
  • Rule Nginx gây lỗi 403 cho editor trong wp-admin: giới hạn rule chỉ áp dụng ngoài location ~ ^/wp-admin, hoặc thêm điều kiện $http_cookie !~ wordpress_logged_in.
  • Vẫn lộ username qua archive link cũ: chạy curl -sI https://yourdomain.com/author/ten-admin/ — nếu trả 200, đổi slug user trong profile hoặc redirect 301 archive đó về trang chủ.
  • Sitemap RSS vẫn lộ tên tác giả: check /feed/, nếu thấy <dc:creator>, dùng filter the_author để thay display name công khai.

Kết luận: chặn user enumeration đáng làm không?

Theo mình, đáng làm và nên làm ngay hôm nay — tổng thời gian cả bài này chỉ khoảng 15 phút. Bảo mật website không phải là một tấm thuẫn thần kỳ mà là chồng nhiều lớp mỏng: chặn enumeration, bật login limit, cập nhật plugin nhanh. Mỗi lớp khiến attacker tốn thêm chi phí, và phần lớn bot lười sẽ bỏ qua site bạn để sang nạn nhân dễ hơn. Sau khi làm xong, bạn chạy lại 3 lệnh curl ở phần kiểm tra để xác nhận cả ba đường đều đã đóng, rồi tách trà ngồi vui.

Thanh Tùng

Mình là Thanh Tùng. Bạn bè gọi mình là "bác sĩ máy tính" vì hễ máy nào có vấn đề là mình muốn mò vào xem sao. Mình viết hướng dẫn theo cách mà mình mong người khác đã viết cho mình ngày xưa — từng bước rõ ràng, không bỏ sót, và nói luôn cái gì hay bị lỗi. Ngoài giờ làm mình chơi guitar, nuôi mèo, và có một con VPS riêng dành riêng cho việc cài thử đủ thứ linh tinh.

Xem tất cả bài viết →

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *