5 phút đọc

PHP vá hai lỗ hổng chiếm máy chủ từ xa, điểm 9,2

PHP 8.2 đến 8.5 vừa ra bản vá cho hai lỗ hổng cho phép chạy mã từ xa không cần đăng nhập, chỉ bằng một request gửi tới trang PHP. Lỗi xảy ra ở đâu, ai bị ảnh hưởng và nên làm gì ngay.

Tối nay (21/10, khoảng 21 giờ giờ Việt Nam) PHP phát hành bốn bản vá cùng lúc: 8.5.12, 8.4.27, 8.3.36 và 8.2.35. Đây là đợt vá mà nhóm bảo mật PHP đã báo trước, vì có hai lỗ hổng đều được chấm 9,2/10 theo CVSS v4, mức nghiêm trọng.

Cả hai đều dẫn tới cùng một hậu quả: kẻ tấn công không cần tài khoản, chỉ cần gửi request HTTP tới một trang PHP là có thể chạy lệnh trên máy chủ dưới quyền của tiến trình web.

Nếu bạn có VPS chạy PHP, một site WordPress, Laravel, hay một app mà AI viết giúp bằng PHP, bài này dành cho bạn.

Mô phỏng lỗi: request multipart làm cạn bộ nhớ, PHP thoát ngang để lại vùng nhớ dở dang, bước dọn dẹp đọc phải nó

Lỗi thứ nhất: hết bộ nhớ giữa chừng (CVE-2026-109618)

Mỗi request PHP có giới hạn bộ nhớ (memory_limit). Khi chạm giới hạn, PHP “nhảy” thẳng ra ngoài để hủy request, không đi hết các bước bình thường.

Vấn đề là có những lúc PHP vừa cấp phát một vùng nhớ nhưng chưa khởi tạo xong thì bị nhảy ra như vậy. Đến bước dọn dẹp cuối request, PHP lại đọc vùng nhớ dở dang đó và làm theo nó. Kẻ tấn công sắp xếp được nội dung vùng nhớ thì điều khiển được chương trình.

Còn làm sao để ép PHP hết bộ nhớ đúng lúc? Bằng một request upload kiểu multipart/form-data được chế sẵn:

  • không khai báo độ dài nội dung, nên lọt qua bước kiểm tra post_max_size
  • mỗi phần của form nhét thật nhiều header, nhỏ trên đường truyền nhưng tốn bộ nhớ gấp nhiều lần khi PHP đọc vào
  • rất nhiều ô chọn file để trống với tên lồng nhau, không bị tính vào giới hạn số file nhưng vẫn sinh ra mảng dữ liệu

Điều đáng sợ: với Apache mod_php, tất cả xảy ra trước khi code của bạn chạy dòng nào. App viết kỹ đến đâu cũng không cứu được. Nhóm nghiên cứu đã chạy được mã từ xa trọn vẹn trên mod_php với cấu hình mặc định.

Với PHP-FPM (kiểu phổ biến khi dùng nginx), phân tích mã nguồn cho thấy cũng bị, nhưng chưa ai dựng được bản khai thác hoàn chỉnh. FrankenPHP được đánh giá là nhiều khả năng bị giống mod_php.

Lỗi thứ hai: đồ cũ của request trước (CVE-2026-109619)

Một tiến trình PHP phục vụ hết request này tới request khác. Nó giữ một số thông tin dùng chung, như thông tin lỗi, phiên đăng nhập (session), trỏ vào bộ nhớ của request đang chạy. Khi request kết thúc, những con trỏ này phải được xóa trước khi bộ nhớ được giải phóng.

Nếu request bị chết giữa chừng (lỗi nghiêm trọng, hết bộ nhớ, quá thời gian chạy), bước xóa có thể bị bỏ qua. Request kế tiếp trên cùng tiến trình lại đụng vào con trỏ cũ trước khi kịp khởi tạo, tức là dùng vùng nhớ đã bị giải phóng. Sắp xếp khéo thì cũng thành chạy mã từ xa.

Hai đường đã được xác nhận khai thác được:

  • Theo dõi tiến độ upload của session (session.upload_progress), bật sẵn theo mặc định, kể cả khi app không hề gọi session_start()
  • Trên PHP 8.5, tùy chọn fatal_error_backtraces khi bật

Lưu ý: tắt hiển thị lỗi, tắt ghi log hay dùng @ để giấu lỗi không giúp gì, vì PHP đụng vào vùng nhớ cũ trước khi quyết định có in lỗi ra hay không.

Ai bị ảnh hưởng

Mọi bản PHP thấp hơn 8.5.12, 8.4.27, 8.3.36, 8.2.35. PHP 8.1 trở xuống đã hết hỗ trợ nên sẽ không có bản vá, nếu còn chạy thì đây là lúc phải nâng cấp.

Bạn dùng hosting quản lý sẵn thì thường nhà cung cấp sẽ tự cập nhật, nhưng nên kiểm tra lại. Còn VPS tự cài thì không ai cập nhật hộ bạn cả.

Nên làm gì ngay

Kiểm tra phiên bản. Chạy php -v trên máy chủ, hoặc xem trong trang quản trị hosting. Nhớ rằng PHP chạy dòng lệnh và PHP chạy web có thể là hai bản khác nhau.

Cập nhật và khởi động lại. Cập nhật qua trình quản lý gói hoặc kéo image Docker mới, rồi khởi động lại toàn bộ PHP-FPM hoặc Apache. Cập nhật xong mà tiến trình cũ còn chạy thì vẫn là bản lỗi. Gói của Ubuntu, Debian, các kho PPA có thể chậm vài ngày so với php.net, nên kiểm tra số phiên bản thật chứ đừng chỉ tin vào lệnh update chạy thành công.

Tắt theo dõi tiến độ upload nếu không dùng. Đặt session.upload_progress.enabled=0 trong php.ini. Chính nhóm PHP khuyên giữ cài đặt này kể cả sau khi đã vá, vì đây là tính năng ít người dùng và ít được kiểm thử.

Nếu chưa vá được ngay, khuyến cáo chính thức có một số cách giảm rủi ro tạm thời:

  • PHP 8.5: đặt fatal_error_backtraces=0
  • Chặn request multipart/form-data ở nginx hoặc Cloudflare nếu app không có chức năng upload
  • Giữ post_max_size nhỏ và giới hạn kích thước request ngay từ tầng phía trước PHP

Các cách này chỉ bịt bớt đường, không thay được bản vá. Khuyến cáo còn nhắc không dùng RLIMIT_AS hay RLIMIT_DATA để giới hạn bộ nhớ, vì chính chúng lại kích hoạt đường lỗi.


Máy chủ của bạn đang chạy PHP bản nào? Đã cập nhật chưa, hay đang chờ gói của distro? Chia sẻ trong cộng đồng Vibe Code & Bảo Mật nhé.

Nguồn

Chia sẻ lên Facebook

Bình luận

Đang tải bình luận…