Một website WordPress doanh nghiệp tại Việt Nam bị đăng 119 bài spam casino, bị cấy 4 tài khoản admin lạ, và có backdoor tự tạo lại file sau khi bị xoá. Bài này ghi lại các dấu hiệu, trình tự xử lý, và những bẫy khiến việc dọn dẹp thất bại, để bạn làm theo nếu website của bạn gặp tình trạng tương tự. Phần lớn các bước làm được chỉ với quyền admin, không cần SSH.
Dấu hiệu nhận biết website WordPress bị chèn spam
Chủ website thường chỉ phát hiện khi Google Search Console báo bất thường, hoặc khi ai đó tìm thấy tên thương hiệu cạnh từ khoá cờ bạc. Trong trường hợp này, các dấu hiệu là:
- Bài viết lạ trong sitemap: mở
/post-sitemap.xml, thấy hàng trăm URL tiếng Pháp hoặc tiếng Anh có từcasino,1xbet,apk. Tổng số bài trong sitemap cao hơn hẳn số bài bạn đã viết. - Ngày đăng bị đặt lùi: bài spam mang ngày tháng 5 đến tháng 7, nhưng ID bài nằm ngay sau các bài bạn mới đăng gần đây. ID là bằng chứng đáng tin hơn ngày đăng.
- Link ẩn trên trang chủ: xem mã nguồn trang chủ, tìm
font-size:0,clip-pathhoặcleft:12000pxtrong các thẻ<a>trỏ tới domain lạ. - Tài khoản lạ: mục Users có Administrator tên kiểu
root,support_xxxx, hoặc email@example.invalid. - Plugin bảo mật bị tắt: Wordfence hoặc plugin tương tự đang ở trạng thái Inactive mà bạn không tắt.
Backdoor ẩn trong mu-plugins: lý do xoá một lần là chưa đủ
Thư mục wp-content/mu-plugins/ chứa các file “must-use”, WordPress tự chạy chúng và không hiện trong danh sách Plugins thông thường. Muốn xem, vào Plugins rồi chọn tab Must-Use. Ở đây có 3 file đáng ngờ: một file nhỏ in link ẩn ra trang, và hai file giống hệt nhau (khoảng 27 KB) tự nhận là “Recovery Channel”.
Chú thích trong mã cho biết mục đích: chống việc “đối thủ mua quyền admin trên site dùng chung” gỡ bỏ nó. Cấu hình lưu trong các dòng wp_options đặt tên ngụy trang nên tồn tại cả sau khi plugin chính bị xoá. Hệ quả thực tế: khi tôi xoá 2 file, chúng được tạo lại sau vài giây.
| Vị trí | Dấu hiệu |
|---|---|
wp-content/mu-plugins/wp-<12 ký tự hex>.php | Không có tên plugin, kích thước lớn bất thường, có kết nối ra domain ngoài |
wp-content/request.php | File 1 KB chứa eval( và $_POST: webshell cho phép chạy lệnh từ xa |
Thư mục lạ trong wp-content/ | Thư mục tên ngẫu nhiên, thư mục ẩn bắt đầu bằng dấu chấm, thư mục “-prev” |
| Plugin vừa xuất hiện | Tên giống chức năng hợp lệ (“script booster”, “link helper”), tác giả không rõ |
| Chỉ số thời gian | File mới sinh ra sau khi bạn đã bắt đầu dọn: kẻ tấn công vẫn còn quyền truy cập |
Quy trình 8 bước xử lý khi chỉ có quyền admin
- Sao lưu và chụp hiện trạng: xuất database, ghi lại danh sách user, plugin, mu-plugins. Nếu hosting có snapshot trước ngày bị xâm nhập, đây là phương án sạch nhất, hãy hỏi nhà cung cấp trước.
- Xoá admin lạ: Users, chọn từng tài khoản lạ, Delete, chọn “Attribute all content to” một tài khoản chính (đừng chọn Delete all content để còn bằng chứng).
- Thu hồi Application Password: vào hồ sơ từng user, kéo xuống mục Application Passwords, Revoke all. Đổi mật khẩu và bật 2FA cho mọi tài khoản còn lại.
- Tìm mã độc: xem tab Must-Use, thư mục
wp-content/, plugin lạ. Dùng Wordfence (cần đăng ký giấy phép miễn phí) để quét. Plugin quản lý file có thể xem thư mục nhưng bản cũ của chúng cũng là đường vào, đừng giữ lại. - Xoá toàn bộ bộ mã trong một lượt: webshell, plugin chính, thư mục lạ, các file mu-plugin. Chờ 30 giây, mở trang chủ và wp-admin để kích hoạt cơ chế tự phục hồi (nếu có), rồi liệt kê lại thư mục để chắc chắn không có file được tạo lại.
- Chuyển bài spam vào thùng rác (không xoá vĩnh viễn): lọc theo ID bài, kiểm tra từng slug có đúng là spam trước khi xoá. Với số lượng lớn, dùng REST API
DELETE /wp-json/wp/v2/posts/{id}từ phiên admin, mặc định chỉ chuyển vào thùng rác. - Xoá cache và kiểm tra sitemap: Empty All Caches (W3 Total Cache, LiteSpeed, WP Rocket…), mở lại sitemap để chắc chắn không còn URL spam, kiểm tra trang chủ không còn link ẩn.
- Theo dõi 7 ngày: mỗi ngày kiểm tra Must-Use, danh sách Users, số URL trong sitemap. Có bài hay file mới nghĩa là nguồn xâm nhập chưa được chặn. Trong Search Console gửi lại sitemap và dùng công cụ Remove URLs cho các URL spam.
Những bẫy dễ gặp
- URL spam vẫn trả HTTP 200 sau khi xoá: theme chuyển mọi URL không tồn tại về trang chủ (soft 404). Google sẽ lâu bỏ index hơn. Cấu hình trả 410 hoặc 404 thật.
- Nút Activate của plugin bảo mật “không phản hồi”: trong trường hợp này là do trang admin quá nặng (plugin bật thật nhưng trang phản hồi chậm hàng chục giây). Hãy chờ và tải lại danh sách trước khi bấm lặp lại; nếu vẫn không bật, nghi có mã chặn plugin bảo mật.
- Bulk trash trả lỗi 500 nhưng bài vẫn vào thùng rác: lỗi xảy ra ở bước hiển thị trang sau thao tác. Luôn kiểm tra lại trạng thái bài trước khi làm lại.
- Đổi mật khẩu chưa đủ: nếu webshell còn, kẻ tấn công không cần mật khẩu. Đổi cả salt trong
wp-config.phpsau khi sạch, để huỷ mọi phiên đăng nhập.
Kết quả sau khi dọn
- Tài khoản: 8 user còn 4, chỉ 1 Administrator.
- Bài spam: 119 bài chuyển vào thùng rác,
post-sitemap.xmltừ 514 xuống 395 URL, 0 URL chứa từ khoá spam. - Mã độc: 5 hạng mục (webshell, plugin chính, thư mục lạ, 2 mu-plugin tự phục hồi) được gỡ trong cùng một lượt, không file nào xuất hiện lại sau 30 giây.
- Trang chủ: không còn khối link ẩn trỏ tới 10 domain casino.
Việc chưa hoàn tất ở thời điểm viết bài: đăng ký giấy phép Wordfence để quét toàn diện, dọn các dòng wp_options ngụy trang (cần phpMyAdmin), đổi mật khẩu database và hosting, cập nhật 20 plugin đang lỗi thời. Nếu hosting có snapshot trước ngày xâm nhập, khôi phục snapshot vẫn là phương án gọn nhất.
Website của bạn có dấu hiệu tương tự?
Tôi nhận tối đa 3 dự án tư vấn mới mỗi tháng. Gửi cho tôi tên miền, tôi sẽ kiểm tra sitemap và trang chủ miễn phí trong buổi đầu.