Ngày 21/10/2026, PHP phát hành bản cập nhật bảo mật khẩn cấp để xử lý hai lỗ hổng nghiêm trọng trong chính PHP runtime. Cặp lỗ hổng này được cộng đồng gọi là PHP2Shell, bao gồm:
- CVE-2026-109618
- CVE-2026-109619
Cả hai lỗ hổng đều được đánh giá ở mức 9.2 Critical theo CVSS. Trong điều kiện phù hợp, kẻ tấn công từ xa không cần xác thực có thể khai thác dịch vụ PHP dễ bị ảnh hưởng để gây rò rỉ bộ nhớ hoặc tiến tới thực thi mã từ xa trên máy chủ.
Điểm quan trọng nhất cần ghi nhớ là: lỗ hổng nằm trong PHP interpreter, không nằm trong riêng WordPress, Laravel, Symfony hay mã nguồn ứng dụng của bạn.
Vì vậy, việc cập nhật framework, nâng phiên bản Composer package hoặc sửa mã nguồn ứng dụng không thể thay thế cho việc cập nhật PHP runtime.
Mục lục
PHP2Shell ảnh hưởng đến những hệ thống nào?
Nếu tổ chức đang vận hành PHP trên máy chủ có kết nối Internet, hãy ưu tiên kiểm tra ngay các hệ thống sử dụng phiên bản trong phạm vi bị ảnh hưởng, từ PHP 5.4 đến PHP 8.5.11.
Phạm vi cần rà soát không chỉ giới hạn ở máy chủ web chính. PHP có thể tồn tại trong nhiều loại workload khác nhau, chẳng hạn:
- PHP-FPM chạy phía sau Nginx hoặc Apache.
- Apache sử dụng mô-đun
mod_php. - Website WordPress, Drupal, Magento, Moodle và các nền tảng PHP khác.
- Docker image được xây dựng từ các image như
php:8.3-fpm. - Pod và workload PHP trong Kubernetes.
- Queue worker xử lý tác vụ nền.
- Tiến trình chạy cron hoặc scheduled job.
- Ứng dụng triển khai trên Cloud Run, ECS, App Engine Flexible và các nền tảng tương tự.
- Phần mềm thương mại hoặc sản phẩm của bên thứ ba tích hợp sẵn PHP runtime.
- Môi trường staging, pre-production và hệ thống thử nghiệm có chứa dữ liệu thật.
Thách thức lớn nhất trong các sự cố liên quan đến runtime là nhiều đội ngũ biết ứng dụng được lưu trữ ở đâu nhưng không chắc chắn binary PHP nào thực sự đang phục vụ lưu lượng production.
Vì sao lỗ hổng PHP runtime đặc biệt nghiêm trọng?
PHP xử lý từng request thông qua một chu trình gồm nhiều bước: tiếp nhận yêu cầu, cấp phát bộ nhớ, xây dựng cấu trúc dữ liệu nội bộ, thực thi mã ứng dụng, giải phóng tài nguyên và chuẩn bị cho request tiếp theo.
Thông thường, các bước này được PHP xử lý âm thầm và nhà phát triển không cần quan tâm đến chi tiết bên trong. Tuy nhiên, PHP2Shell liên quan đến những tình huống đặc biệt trong chu trình này, bao gồm:
- Xử lý lỗi thiếu bộ nhớ.
- Khởi tạo dữ liệu request chưa hoàn tất.
- Giải phóng vùng nhớ.
- Tham chiếu đến dữ liệu đã bị giải phóng.
- Tái sử dụng worker để xử lý nhiều request liên tiếp.
Có thể hình dung mỗi PHP worker như một bàn làm việc dùng chung. Sau khi xử lý một request, hệ thống phải dọn sạch dữ liệu cũ trước khi tiếp nhận request mới. Nếu quá trình dọn dẹp bị gián đoạn hoặc còn sót lại trạng thái cũ, request tiếp theo có thể tương tác với vùng dữ liệu không còn hợp lệ.
Trong trường hợp bị khai thác, hậu quả không chỉ là một trang web bị lỗi hoặc tiến trình bị dừng. Kẻ tấn công có thể tìm cách điều khiển runtime để đọc dữ liệu trong bộ nhớ hoặc thực thi mã trong tiến trình PHP.
Hai CVE trong PHP2Shell được hiểu như thế nào?
| CVE | Bản chất kỹ thuật | Diễn giải đơn giản | Rủi ro đối với hệ thống |
|---|---|---|---|
| CVE-2026-109618 | PHP có thể bị gián đoạn trong quá trình xử lý tình trạng thiếu bộ nhớ khi dữ liệu request mới chỉ được khởi tạo một phần. Giai đoạn dọn dẹp sau đó có thể xử lý trạng thái không hợp lệ như thể nó đã hoàn chỉnh. | Runtime bị dừng giữa chừng trong lúc tạo request rồi cố gắng dọn dẹp một đối tượng chưa được xây dựng đầy đủ. | Luồng xử lý lỗi có thể trở thành điểm kiểm soát do kẻ tấn công tác động. |
| CVE-2026-109619 | Trạng thái thuộc về request vẫn có thể được tham chiếu sau khi vùng nhớ hỗ trợ nó đã bị giải phóng. Một request tiếp theo trên cùng worker có thể sử dụng trạng thái cũ trước khi quá trình khởi tạo hoàn tất. | Một request để lại dữ liệu “dính” trong worker và request tiếp theo đọc phải dữ liệu cũ trước khi môi trường được làm sạch. | Worker PHP chạy lâu và được tái sử dụng có thể làm tăng ý nghĩa của việc rò rỉ hoặc sử dụng trạng thái giữa các request. |
Đây là các vấn đề thuộc nhóm quản lý bộ nhớ và vòng đời dữ liệu. Đội ngũ vận hành không nhất thiết phải tái hiện toàn bộ nghiên cứu khai thác để phản ứng đúng cách. Hành động ưu tiên là:
- Cập nhật PHP runtime lên phiên bản đã được vá.
- Khởi động lại hoặc triển khai lại mọi worker đang chạy.
- Kiểm tra phiên bản PHP thực tế trong môi trường production.
- Rà soát dấu hiệu khai thác hoặc xâm nhập nếu hệ thống từng exposed trên Internet.
Framework được cập nhật có giúp khắc phục PHP2Shell không?
Không. Việc cập nhật framework vẫn cần thiết nhưng giải quyết một nhóm rủi ro khác.
Lỗ hổng trong framework thường liên quan đến route, chức năng cụ thể, thư viện phụ thuộc, cơ chế deserialize hoặc cấu hình ứng dụng. Trong khi đó, PHP2Shell nằm ở tầng thấp hơn trong toàn bộ hệ thống:
Ứng dụng
↓
Laravel / WordPress / Symfony / mã nguồn tùy chỉnh
↓
Composer và các thư viện phụ thuộc
↓
PHP runtime <-- tầng bị ảnh hưởng
↓
Hệ điều hành hoặc container image
Một dự án có thể sử dụng phiên bản Laravel mới nhất, tất cả Composer package đều sạch và không phát hiện lỗi qua SAST, nhưng vẫn dễ bị tấn công nếu PHP interpreter đang chạy là phiên bản chưa được vá.
Do đó, câu hỏi đầu tiên không nên là:
“Repository nào đang sử dụng PHP?”
Mà nên là:
“Những workload nào trong hệ thống thực sự đang thực thi PHP?”
Phiên bản PHP bị ảnh hưởng và phiên bản đã được vá
Theo thông tin công bố, các phiên bản từ PHP 5.4 đến PHP 8.5.11 nằm trong phạm vi cần kiểm tra.
Các bản phát hành upstream ban đầu được xác định là đã khắc phục lỗ hổng gồm:
| Nhánh PHP | Phiên bản đã sửa lỗi |
|---|---|
| PHP 8.5 | 8.5.12 |
| PHP 8.4 | 8.4.27 |
| PHP 8.3 | 8.3.36 |
| PHP 8.2 | 8.2.35 |
PHP 8.1 và các phiên bản cũ hơn đã hết vòng đời hỗ trợ, do đó không nhận được bản vá upstream tương ứng. Nếu đang vận hành các nhánh này, tổ chức không nên chờ một bản vá riêng lẻ mà cần lập kế hoạch chuyển sang một nhánh PHP còn được hỗ trợ.
Lưu ý đối với người dùng Linux distribution
Một số bản phân phối Linux có thể backport bản vá bảo mật vào gói cũ mà không thay đổi hoàn toàn chuỗi phiên bản upstream. Vì vậy, chỉ nhìn vào số phiên bản PHP đôi khi chưa đủ để kết luận hệ thống đã an toàn.
Hãy kiểm tra đồng thời:
- Thông báo bảo mật chính thức của nhà cung cấp hệ điều hành.
- Changelog của package PHP.
- Mã phiên bản package đã cài đặt.
- Thông tin về bản vá CVE trong hệ thống quản lý gói.
Đối với bản PHP tự biên dịch hoặc image PHP chính thức, nên chuyển sang bản upstream đã được sửa lỗi.
Bẫy container: cập nhật máy chủ chưa chắc đã cập nhật PHP
Một trong những sai lầm phổ biến là cập nhật PHP trên máy chủ vật lý hoặc máy chủ ảo nhưng quên rằng ứng dụng thực tế đang chạy bên trong container.
Ví dụ:
FROM php:8.3-fpm
COPY . /var/www/html
Trong trường hợp này, PHP binary được lấy từ container image. Việc cập nhật package PHP trên host không tự động thay đổi binary đã được đóng gói trong image.
Quy trình xử lý đúng cần bao gồm:
Cập nhật PHP base image hoặc package
→ Xây dựng lại image
→ Đẩy image mới với immutable digest
→ Triển khai lại toàn bộ workload
→ Kiểm tra PHP trong container đang chạy
Cần áp dụng quy trình này cho toàn bộ thành phần, không chỉ web container:
- PHP-FPM.
- Queue worker.
- Cron container.
- Container xử lý báo cáo hoặc tác vụ quản trị.
- Job chạy một lần.
- Worker pool tự động mở rộng.
- Pod Kubernetes trong các namespace khác nhau.
Build thành công không đồng nghĩa với việc hệ thống đã được khắc phục. Điều cần chứng minh là workload đang chạy trong production đã sử dụng runtime được vá.
Quy trình xử lý PHP2Shell từng bước
1. Lập danh sách mọi PHP runtime
Bắt đầu bằng việc kiểm tra phiên bản PHP trên máy chủ:
php -v
php --ini
Trong môi trường container, cần xác định image nào chứa PHP và image digest nào đang thực sự được triển khai. Không nên chỉ kiểm tra Dockerfile hoặc file cấu hình trong repository.
Hãy tìm kiếm thông tin trong:
- Dockerfile.
- Helm chart.
- Kubernetes manifest.
- CI/CD workflow.
- Terraform hoặc Pulumi configuration.
- Pipeline triển khai worker.
- Image registry.
- Cấu hình máy chủ web và PHP-FPM.
Đừng bỏ qua các thành phần ít được chú ý như queue worker, scheduled job, maintenance script, batch processing và hệ thống của nhà cung cấp.
2. Xác định hệ thống có nằm trong phạm vi ảnh hưởng không
Sau khi lập danh sách, đối chiếu từng runtime với phạm vi phiên bản bị ảnh hưởng. Cần ghi nhận rõ:
- Phiên bản PHP.
- Kiểu triển khai: VM, bare metal, container hay managed platform.
- Workload đang sử dụng runtime.
- Mức độ tiếp xúc Internet.
- Đơn vị chịu trách nhiệm cập nhật.
- Thời điểm có thể triển khai bản vá.
Đặc biệt ưu tiên các hệ thống có endpoint công khai, upload file, API nhận request lớn hoặc worker xử lý dữ liệu do người dùng kiểm soát.
3. Cập nhật lên bản PHP đã được sửa lỗi
Đối với các nhánh còn được hỗ trợ, hãy nâng cấp lên bản sửa lỗi phù hợp:
- PHP 8.5.12 hoặc mới hơn.
- PHP 8.4.27 hoặc mới hơn.
- PHP 8.3.36 hoặc mới hơn.
- PHP 8.2.35 hoặc mới hơn.
- Bản package do nhà cung cấp xác nhận đã backport bản vá.
Nếu đang dùng PHP 8.1 hoặc cũ hơn, hãy ưu tiên nâng cấp sang một nhánh còn được hỗ trợ thay vì tiếp tục duy trì runtime đã hết vòng đời.
4. Khởi động lại hoặc triển khai lại tiến trình
Cài đặt package mới chỉ là một nửa công việc. Các tiến trình PHP cũ có thể vẫn đang tồn tại trong bộ nhớ và tiếp tục phục vụ request.
Tùy kiến trúc, có thể cần:
- Khởi động lại PHP-FPM.
- Khởi động lại Apache hoặc dịch vụ web liên quan.
- Thay thế toàn bộ container cũ.
- Restart Kubernetes pod.
- Triển khai lại queue worker.
- Chạy lại các scheduled task sử dụng image cũ.
- Đảm bảo autoscaler không giữ lại replica chưa được vá.
Với các lỗ hổng liên quan đến trạng thái request và worker được tái sử dụng, việc để tiến trình cũ tiếp tục chạy là một rủi ro không nên chấp nhận.
5. Xác minh môi trường đang hoạt động
Kiểm tra phiên bản từ một tiến trình mới được khởi động:
php -v
Trong container, cần xác minh thêm image digest:
php -v
cat /etc/os-release
Không nên chỉ dựa vào log build hoặc phiên bản trên máy tính cá nhân. Một rollout có thể thất bại một phần, image tag có thể bị tái sử dụng hoặc autoscaler có thể giữ lại replica cũ.
Danh sách cần xác minh gồm:
- Phiên bản PHP của web workload.
- Phiên bản PHP của worker.
- Phiên bản PHP của cron job.
- Image digest đang chạy.
- Số lượng replica cũ còn tồn tại.
- Trạng thái rollout trong hệ thống điều phối.
WAF có thể bảo vệ hệ thống thay cho bản vá không?
Không. WAF có thể giúp giảm rủi ro trong thời gian triển khai bản vá nhưng không thể thay thế việc cập nhật PHP interpreter.
Trong giai đoạn xử lý, đội ngũ có thể cân nhắc:
- Áp dụng managed WAF rule.
- Giới hạn kích thước request body.
- Giới hạn tốc độ request bất thường.
- Tăng cường kiểm soát endpoint upload.
- Đặt ứng dụng sau lớp reverse proxy hoặc CDN.
- Giám sát request có payload bất thường.
Nên triển khai rule ở chế độ preview hoặc canary trước nếu hệ thống cho phép, sau đó đánh giá false positive và chuyển sang chế độ enforce.
Tuy nhiên, WAF chỉ nhìn thấy lưu lượng đi qua nó và chỉ chặn được những mẫu tấn công mà rule nhận diện. Nó không xử lý được mọi đường truy cập, đặc biệt là:
- Worker nội bộ.
- API không đi qua WAF.
- Luồng xử lý từ mạng riêng.
- Scheduled job.
- Request được chuyển tiếp qua một dịch vụ trung gian.
Vì vậy, hãy coi WAF là biện pháp phòng thủ tạm thời hoặc bổ sung. Biện pháp khắc phục chính vẫn là cập nhật và khởi động lại PHP runtime.
Cần giám sát những dấu hiệu nào sau khi công bố lỗ hổng?
Nếu hệ thống từng sử dụng phiên bản PHP bị ảnh hưởng và có kết nối Internet, hãy tiến hành rà soát log và telemetry để phát hiện dấu hiệu bất thường.
Các nguồn dữ liệu nên kiểm tra bao gồm:
- Web server access log.
- Web server error log.
- PHP-FPM log.
- Apache log.
- WAF và load balancer event.
- Process execution telemetry.
- Container runtime log.
- Application error và restart telemetry.
- Kết quả quét image sau khi rebuild.
- Thông tin từ hệ thống EDR hoặc SIEM.
Một số dấu hiệu đáng chú ý:
- Tăng đột biến lỗi HTTP 5xx.
- PHP-FPM hoặc web worker liên tục bị crash.
- Request có kích thước bất thường.
- Tiến trình PHP khởi chạy shell hoặc binary không quen thuộc.
- Xuất hiện lệnh như
sh,bash,curlhoặcwgetkhông phù hợp với hoạt động bình thường. - Máy chủ thực hiện các lượt tải file không được giải thích.
- Thay đổi bất thường trong thư mục upload hoặc thư mục tạm.
- Kết nối outbound đến địa chỉ IP hoặc domain đáng ngờ.
Các dấu hiệu trên không tự động chứng minh hệ thống đã bị khai thác. Tuy nhiên, chúng cần được điều tra theo quy trình ứng phó sự cố và nên bảo toàn bằng chứng liên quan trước khi tiến hành dọn dẹp.
Những sai lầm phổ biến khi xử lý PHP2Shell
“Chúng tôi đã cập nhật WordPress nên an toàn rồi”
Cập nhật WordPress có thể giúp khắc phục lỗ hổng của WordPress, nhưng không thay thế PHP binary đang chạy WordPress. Hai lớp này cần được xử lý riêng.
“Chúng tôi đã nâng cấp package trên server”
Điều đó chỉ có ý nghĩa nếu ứng dụng thực sự sử dụng PHP từ package trên server. Nếu workload chạy trong container, immutable image hoặc sản phẩm của nhà cung cấp, package trên host có thể không ảnh hưởng gì đến tiến trình đang phục vụ request.
“Repository không có lỗi theo công cụ quét”
Quét mã nguồn không chứng minh runtime production đã được cập nhật. Cần quét container image, kiểm tra image digest và xác minh phiên bản của tiến trình đang hoạt động.
“Chúng tôi đang dùng PHP 8.1 và hệ thống vẫn ổn định”
Ổn định không đồng nghĩa với được hỗ trợ bảo mật. PHP 8.1 và các nhánh cũ hơn đã hết vòng đời. Đây là thời điểm cần chuyển kế hoạch nâng cấp PHP thành công việc ưu tiên trong ứng phó rủi ro.
“Đã có WAF rule nên chưa cần cập nhật”
WAF là biện pháp giảm thiểu tạm thời. Nó không loại bỏ lỗi trong interpreter và không bảo vệ toàn bộ các luồng xử lý nội bộ. Đừng để WAF trở thành lý do trì hoãn bản vá.
Checklist xử lý lỗ hổng PHP2Shell
- ☐ Liệt kê toàn bộ web server, worker và scheduled job có sử dụng PHP.
- ☐ Xác định phiên bản PHP thực tế của từng workload.
- ☐ Kiểm tra các hệ thống có nằm trong phạm vi từ PHP 5.4 đến PHP 8.5.11 hay không.
- ☐ Nâng cấp lên PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 hoặc bản package đã được nhà cung cấp xác nhận đã vá.
- ☐ Chuyển PHP 8.1 và các phiên bản cũ hơn sang nhánh còn được hỗ trợ.
- ☐ Rebuild custom image, tránh phụ thuộc vào cache cũ.
- ☐ Đẩy image mới với digest bất biến.
- ☐ Redeploy toàn bộ web workload, worker và cron workload.
- ☐ Khởi động lại các tiến trình PHP chạy lâu.
- ☐ Xác minh phiên bản PHP và image digest trong môi trường live.
- ☐ Kiểm tra các replica cũ còn đang hoạt động.
- ☐ Áp dụng WAF hoặc edge control tạm thời nếu cần.
- ☐ Rà soát log, EDR, WAF và process telemetry.
- ☐ Bảo toàn bằng chứng nếu phát hiện dấu hiệu xâm nhập.
- ☐ Ghi nhận môi trường đã xác minh và môi trường còn tồn đọng.
Doanh nghiệp nên chuẩn bị gì sau khi xử lý?
PHP2Shell cho thấy việc quản lý runtime cần được đưa vào quy trình quản trị tài sản và quản lý lỗ hổng thường xuyên. Một số biện pháp nên triển khai lâu dài gồm:
- Duy trì danh mục đầy đủ các PHP runtime trong toàn tổ chức.
- Gắn phiên bản runtime với từng ứng dụng, container image và workload.
- Thiết lập quy trình cập nhật base image định kỳ.
- Không sử dụng tag container có thể bị thay đổi mà không khóa digest.
- Quét image trong CI/CD trước khi triển khai.
- Kiểm tra runtime trong môi trường production sau mỗi lần rollout.
- Đưa queue worker và scheduled job vào phạm vi quản lý bản vá.
- Định nghĩa SLA riêng cho lỗ hổng Critical trong runtime.
- Chuẩn hóa quy trình restart hoặc thay thế tiến trình PHP dài hạn.
- Kiểm thử khả năng rollback nhưng không quay lại image chưa được vá.
Kết luận
PHP2Shell là lời nhắc rõ ràng rằng bảo mật ứng dụng không chỉ nằm ở mã nguồn, framework hay thư viện Composer. PHP runtime cũng là một thành phần quan trọng trong chuỗi cung ứng phần mềm và có thể trở thành điểm tấn công trực tiếp khi xuất hiện lỗi nghiêm trọng.
Các đội ngũ phản ứng hiệu quả thường đã biết trước:
- PHP runtime đang tồn tại ở đâu.
- Workload nào đang sử dụng từng phiên bản.
- Container image được xây dựng và triển khai như thế nào.
- Cách cập nhật toàn bộ worker và replica.
- Cách xác minh bản vá đã thực sự đến production.
Đừng chỉ cập nhật ứng dụng. Hãy cập nhật interpreter, khởi động lại các tiến trình cũ và kiểm tra trực tiếp môi trường đang phục vụ người dùng.
Hãy vá PHP, triển khai lại toàn bộ workload và xác minh kết quả trong production.



