CVE-2026-87902 Đã Leo Thang Thành RCE Qua pearcmd: Săn Dấu Vết Trong Log Bằng WP-CLI Từ A Đến Z

Câu trả lời nhanh
CVE-2026-87902 đã bị khai thác thật qua chuỗi pearcmd: kẻ tấn công ghi file PHP vào /tmp bằng config-create, kèm Nuclei template công khai. Bạn rà access log bằng grep tìm pagename chứa %2e%2e, pearcmd hoặc config-create, kiểm tra /tmp tìm file .php lạ, rồi nâng cấp WordPress 7.1.2 hoặc bản backport về tận 4.7.37.

Hôm qua mình vừa viết bài hướng dẫn vá WordPress 7.1.2 cho lỗ hổng CVE-2026-87902. Nếu bạn nghĩ vá xong là xong chuyện thì hôm nay mình có tin không vui: dữ liệu tường lửa của Patchstack cho thấy kẻ tấn công đã đi từ dò quét sang ghi file PHP thật lên đĩa chỉ trong vòng 24 giờ, và một Nuclei template công khai đã xuất hiện. Nghĩa là bất kỳ ai cũng có thể quét cả danh sách host chỉ bằng một dòng lệnh.

Trong bài này, mình sẽ đi từng bước: điều gì đã thay đổi, làm sao biết site mình có bị dò hay bị thành công hay không bằng lệnh grep trên access log, kiểm tra /tmp bằng SSH, và hai lớp phòng thủ tạm thời nếu bạn chưa nâng cấp được ngay.

CVE-2026-87902 đã leo thang lên mức nào?

CVE-2026-87902 leo thang thành RCE qua pearcmd trên WordPress

Theo dữ liệu Patchstack cập nhật ngày 23/9/2026, lưu lượng tấn công đã tăng hơn 10 lần so với buổi tối ngày đầu, đi qua ba giai đoạn rõ rệt. Giai đoạn một là dò xem lỗ hổng tồn tại bằng cách include các file core vô hại. Giai đoạn hai kiểm tra xem pearcmd.php có gọi được không. Giai đoạn ba là dùng pearcmd với config-create để ghi file PHP do kẻ tấn công kiểm soát nội dung vào /tmp. Đó là arbitrary file write, tức là code execution thật sự, không còn là thí nghiệm.

Vì sao kẻ tấn công dùng pearcmd để khai thác?

Bản thân lỗ hổng là Local File Inclusion, nghĩa là chỉ включ được file có sẵn trên đĩa. Nhưng nếu server PHP bật register_argc_argv, query string sẽ được truyền thành $argv cho file được include. File pearcmd.php của PEAR lại nhận lệnh từ $argv, trong đó có lệnh config-create cho phép ghi file mới với nội dung tùy ý. Chuỗi bắt lại với nhau: LFI cộng register_argc_argv cộng pearcmd bằng RCE. Đây chính là kỹ thuật từng làm nên CVE-2024-25644 trong RaspAP cách đây hai năm.

Cách kiểm tra access log xem site có bị dò không?

Bạn SSH vào server và chạy các lệnh grep sau trên access log của Nginx hoặc Apache. Với Nginx mặc định Ubuntu/Debian, log nằm ở /var/log/nginx/access.log. Tín hiệu có độ tin cậy cao nhất là tham số pagename chứa chuỗi duyệt thư mục đã encode:

grep -iE 'pagename=.*(%.?2e%.?2e|%252e%252e)' /var/log/nginx/access.log

Tín hiệu thứ hai: pagename bắt đầu bằng templates%2f hoặc kèm page_id, cặp tham số này gần như không bao giờ xuất hiện cùng nhau trong traffic bình thường:

grep -iE 'pagename=templates(%2f|%252f)' /var/log/nginx/access.log
grep -iE 'page_id=.+&pagename=' /var/log/nginx/access.log

Tín hiệu giai đoạn hai và ba, mức độ nghiêm trọng nhất — nếu grep ra dòng nào thì xem như có người đã thử ghi file lên server bạn:

grep -iE '(pearcmd|config-show|config-create)' /var/log/nginx/access.log
grep -iE 'cve-2026-87902-poc|nuclei-cve-2026-87902' /var/log/nginx/access.log

Lưu ý: kẻ tấn công đã chuyển sang dùng POST cho phần lớn request vì WordPress đọc pagename từ POST body trước query string, và spoof user agent là trình duyệt. Đừng lọc log chỉ theo GET hay theo user agent, sẽ sót.

Làm sao biết site đã bị ghi file thành công?

Trên chính server, kiểm tra /tmp và /var/tmp tìm các file .php bất thường:

ls -la /tmp/*.php /var/tmp/*.php 2>/dev/null
find /tmp /var/tmp -name '*.php' -mtime -7 -ls

Các tên file Patchstack đã quan sát được: wp-pear-rce-flag.php, poc87902.php, luci_random.php, zeta_random.php. Nếu thấy một trong các file kiểu này, hoặc nội dung chứa chuỗi như CVE-2026-87902-POC-OK hay LUCIFER-RCE-OK, thì host của bạn đã bị ghi file thành công. Trạng thái lúc này là compromised, không phải bị quét hụt. Bạn cần cách ly, đổi mật khẩu, dựng lại từ backup sạch thay vì chỉ xóa file rồi coi như xong.

Một dấu hiệu khác trong access log: một URL trang bình thường nhưng response trả về nội dung OPML hoặc RSS feed. Kèm mã 200 nghĩa là lệnh include đã chạy thật trên host bạn trong cửa sổ trước khi vá. Những site đã online từ trước ngày 22/9 nên rà lịch sử log theo tiêu chí này.

Chưa nâng cấp được thì chặn tạm bằng cách nào?

Cách 1: từ chối mọi giá trị pagename chứa chuỗi duyệt thư mục. Slug trang thật không bao giờ có %2e%2e nên chặn không ảnh hưởng traffic hợp lệ. Với Nginx, thêm vào server block:

if ($args ~* "pagename=.*(%.?2e%.?2e|%252e%252e)") {
    return 403;
}
if ($request_body ~* "(%.?2e%.?2e|pearcmd|config-create)") {
    return 403;
}

Cách 2: tắt register_argc_argv trong php.ini. Lựa chọn này không vá được inclusion nhưng chặt đứt chuỗi pearcmd, biến lỗ hổng từ code execution trở về information leak:

register_argc_argv = Off

Sau đó restart PHP-FPM. Kiểm tra bằng lệnh php -i | grep register_argc_argv. Lưu ý: một số ứng dụng CLI cũ phụ thuộc argv, nếu server bạn chạy nhiều app thì test kỹ trước khi áp dụng.

Nâng cấp lên bản vá thì làm thế nào cho đúng?

WordPress đã backport bản vá về tận 4.7.37, nên site cũ cũng vá được mà không cần nhảy version lớn. Kiểm tra và nâng cấp bằng WP-CLI:

sudo -u www-data wp core version --path=/var/www/yoursite/public_html
sudo -u www-data wp core update --path=/var/www/yoursite/public_html
sudo -u www-data wp core verify-checksums --path=/var/www/yoursite/public_html

Nếu bạn quản lý nhiều site, tham khảo bài hướng dẫn vá và rà soát CVE-2026-87902 bằng WP-CLI mình viết hôm qua để chạy hàng loạt. Trước khi update, backup database và thư mục wp-content. Sau khi update, verify-checksums để chắc không file core nào bị thay đổi.

Có những lỗi thường gặp khi rà soát log không?

Mình liệt kê vài cái mình gặp hoặc thấy người khác dính:

Một, grep chỉ trên access log mà quên error log. Payload dài gây 414 Request URI Too Large sẽ nằm ở error log chứ không phải access log. Kiểm tra cả hai.

Hai, log đã bị logrotate nén thành .gz. Chạy zgrep thay grep trên các file đó, không thì bạn chỉ rà được vài ngày gần đây mà tưởng là an toàn:

zgrep -iE 'pearcmd|config-create' /var/log/nginx/access.log.*.gz

Ba, chỉ tìm đúng chuỗi payload một biến thể. Payload có thể uppercase hex, single hoặc double encoding, và độ sâu duyệt từ 1 đến 12 cấp. Dùng regex như mình đưa ở trên thay vì chuỗi cố định.

Bốn, bỏ qua CDN. Nếu site bạn đứng sau Cloudflare, access log gốc của Nginx chỉ thấy IP edge. Rà thêm Firewall Events trên dashboard Cloudflare với filter URI contains pearcmd.

Kết luận

Từ bản patch ngày 22/9 đến trình quét công khai trên Nuclei chỉ mất chưa đầy 2 ngày. Đây là nhịp độ mới của an ninh WordPress thời AI: khoảng cách giữa patch diff và công cụ khai thác hoàn chỉnh đang co ngắn lại từng tuần. Nếu bạn chưa nâng cấp 7.1.2 hoặc một bản backport, hôm nay là lúc làm, không phải tuần sau. Sau khi vá, dành 10 phút chạy các lệnh grep ở trên để biết cửa sổ lỗ hổng của mình có ai kịp bò vào hay không.

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 *