Tối 21/10/2026 (giờ Việt Nam), PHP phát hành bản vá lỗ hổng PHP PHP2Shell cho phép chạy code từ xa mà không cần đăng nhập, cả hai lỗ hổng được chấm 9.2 theo CVSS v4.0. Bản vá có ở PHP 8.5.12, 8.4.27, 8.3.36 và 8.2.35. Ai đang chạy website PHP thì nên cập nhật ngay, không đợi lịch bảo trì định kỳ.
Bài này tổng hợp những gì đã biết về lỗ hổng, cách kiểm tra máy chủ của mình có bị ảnh hưởng không, và quy trình vá trên ba môi trường phổ biến ở Việt Nam: VPS cài PHP thông thường với Apache hoặc Nginx, VPS chạy CyberPanel (OpenLiteSpeed), và máy chủ chạy Docker. Phần OpenLiteSpeed được viết lại từ đúng những gì chúng tôi gặp khi vá ba VPS sáng 22/10, kể cả các lỗi lệnh.
Đối với các doanh nghiệp đang vận hành hệ thống thương mại điện tử, ứng dụng SaaS hoặc website doanh nghiệp quy mô lớn trên nền tảng máy chủ độc lập, việc đảm bảo hạ tầng vững chắc là ưu tiên sống còn.
1. Chuyện gì đã xảy ra?
Đợt vá này không theo lịch thường lệ. Chi tiết về hai lỗ hổng bị rò rỉ trước ngày công bố dự kiến, nên nhóm bảo mật PHP phải ra thông báo trước rồi đẩy bản vá sớm.
| Thời điểm (UTC) | Giờ Việt Nam | Sự kiện |
|---|---|---|
| 21/10, khoảng 13:45 đến 13:52 | 21/10, khoảng 20:45 | PHP phát hành 8.5.12, 8.4.27, 8.3.36, 8.2.35. Sury (Debian) và Arch có gói vá sau vài phút |
| 21/10 | 21/10 | Cloudflare cập nhật khẩn bộ luật WAF managed để chặn kiểu tấn công này |
| 21/10, khoảng 05:40 | 21/10, khoảng 12:40 | Các báo cáo trong ngành bắt đầu nêu hai mã CVE-2026-109618 và CVE-2026-109619 |
| 20/10, 19:33 | 21/10, 02:33 | Jakub Zelenka gửi thông báo trước lên danh sách php.announce, hẹn phát hành 14:00 UTC ngày 21/10 |
| 20/10 | 20/10 đến 21/10 | Thông tin về hai lỗ hổng bắt đầu lan ra trước thời hạn công bố |
Thông báo trước của PHP có ghi rõ họ có thể phát hành sớm hơn nếu chi tiết lộ ra hoặc thấy dấu hiệu bị khai thác thực tế. Thực tế bản vá ra trước giờ hẹn vài phút.
Theo thông báo khẩn từ PHP Security Team, đợt phát hành bảo mật này được ấn định chính xác vào lúc 14:00 UTC ngày 21/10/2026 (tức 21:00 tối nay theo giờ Việt Nam). Đội ngũ phát triển PHP đã đưa ra cảnh báo sớm để cộng đồng kỹ thuật toàn cầu kịp thời chuẩn bị kế hoạch trực chiến và sao lưu dữ liệu.
Điểm số CVSS v4.0 9.2 (Critical) là thang đo mức độ nguy hiểm ở cấp độ cao nhất trong bảo mật phần mềm. Thông thường, các lỗ hổng đạt điểm số trên 9.0 sẽ liên quan trực tiếp đến các kịch bản:
- Thực thi mã từ xa (Remote Code Execution – RCE): Kẻ tấn công có thể gửi các gói tin đặc thù qua giao thức HTTP/HTTPS để ép máy chủ thực thi các đoạn mã độc mà không cần tài khoản đăng nhập (Unauthenticated).
- Tràn bộ đệm hoặc lỗi phân tích dữ liệu nhị phân (Buffer Overflow / Memory Corruption): Gây tê liệt dịch vụ (Denial of Service – DoS) hoặc trích xuất dữ liệu nhạy cảm trực tiếp từ bộ nhớ RAM của tiến trình PHP-FPM.
- Chiếm quyền điều khiển hoàn toàn máy chủ (Full Server Takeover): Sau khi thâm nhập qua tiến trình PHP, tin tặc có thể leo thang đặc quyền để kiểm soát toàn bộ hệ điều hành Linux, đánh cắp cơ sở dữ liệu hoặc cài mã độc tống tiền (Ransomware).
2. PHP2Shell là gì và ai bị ảnh hưởng
PHP2Shell là tên nhóm nghiên cứu đặt cho hai lỗi nằm trong lõi PHP, không phải trong WordPress, Laravel hay một thư viện nào. 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 bất kỳ trên máy chủ.
Ở mức khái quát, cả hai lỗi đều liên quan tới cách PHP quản lý bộ nhớ khi xử lý request:
- Một lỗi xoay quanh tính năng theo dõi tiến trình upload (
session.upload_progress). Một request có thể để lại tham chiếu tới vùng nhớ đã được giải phóng, và request kế tiếp chạy trên cùng worker có thể dùng lại tham chiếu đó trước khi PHP kịp khởi tạo lại. - Lỗi còn lại dẫn tới thực thi code thông qua việc làm hỏng bộ nhớ khi tiến trình chạm ngưỡng hết bộ nhớ (OOM).
Các nguồn đang gán hai mã CVE cho hai lỗi theo thứ tự khác nhau: bảng của Wiz xếp lỗi upload-progress vào CVE-2026-109618, còn advisory của PHP và trang php2shell.com xếp nó vào CVE-2026-109619. Với người vận hành thì điều này không đổi gì, vì một bản cập nhật sửa cả hai.
Về phạm vi, PHP xác định mọi bản cài đặt phục vụ web request đều có rủi ro: PHP-FPM, Apache với mod_php, php-cgi, FrankenPHP và LiteSpeed. Mod_php được đánh giá rủi ro cao nhất. LiteSpeed (LSAPI) có cách chạy worker giống FPM; khả năng bị khai thác theo từng ứng dụng được coi là cao, dù chưa có bằng chứng kiểm chứng công khai.
PHP chạy dòng lệnh thuần (cron, script CLI) không nhận request HTTP nên ít bị phơi nhiễm hơn. Nhưng hầu như không máy chủ web nào chỉ có CLI, nên đừng dựa vào đó để hoãn vá.
3. Những Hệ Thống Nào Đang Nằm Trong Vùng Rủi Ro Cao?
PHP là ngôn ngữ lập trình kịch bản đang vận hành hơn 75% số lượng website trên toàn thế giới. Do đó, tác động của đợt vá lỗi này là vô cùng sâu rộng, đặc biệt đối với:
- Hệ sinh thái WordPress & WooCommerce: Chiếm tỷ trọng lớn nhất, nơi các cổng thanh toán và dữ liệu đơn hàng nhạy cảm của khách hàng được lưu trữ liên tục.
- Các ứng dụng viết bằng Laravel, Symfony, CodeIgniter: Các hệ thống ERP, CRM, phần mềm quản lý nội bộ và API backend phục vụ ứng dụng di động.
- Các phiên bản PHP chịu ảnh hưởng: Toàn bộ các nhánh đang được hỗ trợ chính thức gồm PHP 8.1, PHP 8.2, PHP 8.3, PHP 8.4 và cả các bản thử nghiệm PHP 8.5 đều sẽ nhận các bản cập nhật phụ (point releases) tương ứng.
4. Phiên bản nào đã an toàn
Nguyên tắc đơn giản: nhánh còn được hỗ trợ thì lên bản vá; nhánh đã hết hỗ trợ (EOL) thì không có bản phát hành chính thức nào cứu được.
| Nhánh PHP | Bản vá đầu tiên | Ghi chú |
|---|---|---|
| 8.5 | 8.5.12 | |
| 8.4 | 8.4.27 | |
| 8.3 | 8.3.36 | |
| 8.2 | 8.2.35 | Chỉ còn nhận bản vá bảo mật tới 31/12/2026, nên lên kế hoạch chuyển nhánh |
| 8.1, 8.0, 7.4 | Không có bản chính thức | Nhóm bảo mật PHP phát hành bản backport tối thiểu dạng mã nguồn, dành cho ai tự build |
| 5.6 và cũ hơn | Không có | Chúng tôi chưa thấy thông tin chính thức nào về nhánh này |
Máy chủ cài PHP qua gói của nhà phân phối (Ubuntu, Debian, RHEL) có thể giữ nguyên số version cũ nhưng đã được backport bản vá. Khi đó phải xem changelog của gói hoặc thông báo bảo mật của nhà phân phối, không chỉ nhìn vào số version.
Ai đang dùng kho rpms.remirepo.net cần lưu ý: đây là kho do tình nguyện viên duy trì và đã báo không có bản cập nhật trong ngày 21/10. Khuyến nghị là chuyển sang gói của nhà phân phối hoặc tự build để vá ngay.
5. Quy trình chung cho mọi môi trường
Dù máy chủ chạy panel nào, việc vá đều đi qua bốn bước. Bỏ qua bước nào cũng có thể khiến máy chủ vẫn hở dù bạn tưởng đã vá xong.
- Kiểm kê. Liệt kê mọi bản PHP đang có trên máy. Một VPS chạy CyberPanel lâu năm thường có năm, sáu bản song song, và site cũ nhất thường dùng bản cũ nhất.
- Vá. Cập nhật đúng các gói PHP, không chạy
apt upgradetoàn hệ thống trong lúc khẩn cấp. Nâng cả MariaDB, kernel cùng lúc chỉ làm tăng rủi ro mà không giúp gì cho lỗ hổng này. - Khởi động lại tiến trình PHP. Gói mới nằm trên đĩa nhưng worker đang chạy vẫn dùng binary cũ trong bộ nhớ. Không restart thì coi như chưa vá.
- Xác nhận. Kiểm tra lại version thật của từng bản PHP và thời điểm khởi động của các tiến trình.
Trước bước 2, nên snapshot VPS và làm vào giờ thấp điểm. Restart PHP và web server cắt các request đang chạy trong vài giây.
Một thay đổi hành vi cần biết sau khi lên bản vá: PHP thêm một giới hạn bộ nhớ cứng thứ hai, cao hơn memory_limit. Tiến trình chạm ngưỡng này bị dừng ngay và các shutdown function không được chạy. Ứng dụng nào dựa vào register_shutdown_function để ghi log hay dọn dẹp khi hết bộ nhớ thì nên kiểm thử lại.
6. Vá trên VPS cài PHP thông thường (Apache, Nginx)
Đây là mô hình phổ biến nhất: PHP cài từ trình quản lý gói, chạy dưới dạng PHP-FPM sau Nginx (hoặc Apache với proxy_fcgi), hoặc dạng mod_php trong Apache. Nginx và Apache tự chúng không cần vá; thứ cần vá là gói PHP và tiến trình đang chạy nó.
Xác định PHP lấy từ đâu và chạy theo cách nào
Ubuntu/Debian:
dpkg -l | awk '/^ii/ && ($2 ~ /^php[0-9.]+-(fpm|cli)$/ || $2 ~ /^libapache2-mod-php/) {print $2, $3}'
grep -rhiE 'ondrej|sury' /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null
AlmaLinux/Rocky/RHEL:
rpm -qa 'php*' | sort
dnf repolist | grep -i remi
Cách PHP đang được phục vụ:
systemctl list-units --type=service --no-legend | grep -E 'php.*fpm'
apache2ctl -M 2>/dev/null | grep -i php || httpd -M 2>/dev/null | grep -i php
Có service FPM nghĩa là PHP chạy qua FPM. Lệnh thứ hai trả về php_module nghĩa là Apache đang nạp mod_php, trường hợp được PHP đánh giá rủi ro cao nhất.
Tình trạng gói vá theo nguồn
| Nguồn gói | Tình trạng ngày 21-22/10 | Cách kiểm tra |
|---|---|---|
| packages.sury.org (Debian) | Có gói vá vài phút sau khi PHP phát hành | Số version lên 8.x.y mới |
| PPA ondrej (Ubuntu) | Đã có gói cho Ubuntu 24.04 trên Launchpad | Số version lên 8.x.y mới |
| Debian 13 security | Đã có gói vá cho php8.4 | Changelog của gói |
| Kho chính thức Ubuntu, RHEL AppStream | Theo thông báo bảo mật của nhà phân phối | Changelog của gói, vì số version có thể giữ nguyên |
| Remi (rpms.remirepo.net) | Không có bản cập nhật trong ngày 21/10 | Nên chuyển sang gói nhà phân phối hoặc tự build |
Với gói của nhà phân phối, đừng chỉ nhìn số version. Ubuntu 24.04 vẫn gọi PHP là 8.3.x với hậu tố ubuntu, bản vá được backport vào. Kiểm tra bằng changelog:
zcat /usr/share/doc/php8.3-fpm/changelog.Debian.gz | grep -m3 -E 'CVE-2026-10961[89]'
rpm -q --changelog php-fpm | grep -m3 -E 'CVE-2026-10961[89]'
Cập nhật
Ubuntu/Debian, chỉ nâng các gói PHP đang cài:
apt update
apt install --only-upgrade $(dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' '*php*' | awk '$1=="ii"{print $2}')
Mẫu *php* có thể kéo theo cả phpMyAdmin hoặc thư viện PHP của ứng dụng khác. Đọc danh sách apt in ra trước khi gõ Y.
AlmaLinux/Rocky/RHEL:
dnf update 'php*'
Máy dùng Remi theo kiểu cài song song nhiều bản (php83-php-fpm, php84-php-fpm…) thì cập nhật theo tên gói đó, ví dụ dnf update 'php83-*', khi Remi có bản mới.
Khởi động lại
| Cách PHP chạy | Lệnh sau khi cập nhật |
|---|---|
| PHP-FPM trên Ubuntu/Debian | systemctl restart 'php*-fpm' |
| PHP-FPM trên RHEL | systemctl restart php-fpm (Remi song song: systemctl restart php83-php-fpm…) |
| Apache mod_php | systemctl restart apache2 hoặc systemctl restart httpd |
Nginx không cần restart vì nó chỉ chuyển request sang FPM. Reload FPM cũng nạp được binary mới, nhưng restart cho chắc chắn hơn trong đợt vá khẩn.
Xác nhận
for b in /usr/sbin/php-fpm*; do echo "$b => $($b -v | head -1)"; done
ps -eo pid,lstart,cmd | grep -E '[p]hp-fpm|[a]pache2|[h]ttpd'
Tiến trình master và worker phải có giờ khởi động sau lúc restart. Với mod_php, cách chắc nhất là tạo tạm một file phpinfo() trong web root, mở bằng trình duyệt xem version, rồi xóa ngay.
7. Máy chủ có control panel khác
| Panel | Lệnh cập nhật PHP |
|---|---|
| cPanel (EasyApache 4) | dnf update 'ea-php*' (CentOS 7 dùng yum) |
| CloudLinux alt-php | yum update 'alt-php*' |
| Plesk | plesk installer update |
| DirectAdmin | da build update && da build php |
Sau khi cập nhật, restart dịch vụ PHP của panel tương ứng và xác nhận như trên.
Biện pháp tạm cho máy chưa có gói vá
Thay vì sửa php.ini gốc, tạo một file cấu hình riêng để dễ gỡ khi đã vá:
# Ubuntu/Debian
for d in /etc/php/*/fpm/conf.d /etc/php/*/apache2/conf.d; do
[ -d "$d" ] && echo 'session.upload_progress.enabled = Off' > "$d/99-php2shell.ini"
done
# RHEL
echo 'session.upload_progress.enabled = Off' > /etc/php.d/99-php2shell.ini
Rồi restart FPM hoặc Apache. Trong pool FPM, nên khóa thêm bằng php_admin_flag[session.upload_progress.enabled] = off để ứng dụng không bật lại được qua .user.ini. Giới hạn của biện pháp này được nói ở phần sau.
8. Vá trên VPS chạy CyberPanel
CyberPanel dùng OpenLiteSpeed, và PHP ở đây là các gói lsphpXY lấy từ kho của LiteSpeed (rpms.litespeedtech.com), cài vào /usr/local/lsws/lsphpXY/. Gói PHP của Ubuntu không liên quan. Các lệnh dưới đây dành cho Ubuntu; AlmaLinux/Rocky dùng dnf tương ứng.
Tối 21/10 kho LiteSpeed chưa có gói vá. Sáng 22/10, khi chúng tôi kiểm tra trên Ubuntu 24.04 (noble) và 22.04 (jammy), kho đã có đủ 8.2.35, 8.3.36, 8.4.27 và 8.5.12.
Bước 1: kiểm kê
for b in /usr/local/lsws/lsphp*/bin/php; do echo "$b => $($b -v | head -1)"; done
Sau đó xem kho đã có bản mới cho các gói đang cài chưa:
apt update
dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' 'lsphp*' | awk '$1=="ii"{print $2}' | grep -E '^lsphp[0-9]+$' | xargs apt-cache policy | grep -E '^lsphp|Installed|Candidate'
Cột Candidate cao hơn Installed là có bản mới. Nếu một thư mục lsphpXY có trên đĩa mà không xuất hiện trong danh sách này, bản PHP đó được cài ngoài apt (build tay hoặc chép từ máy khác) và apt sẽ không bao giờ cập nhật nó. Chúng tôi gặp đúng trường hợp này với một bản PHP 5.6.
Bước 2: chỉ nâng các gói lsphp
apt install --only-upgrade $(dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' 'lsphp*' | awk '$1=="ii"{print $2}')
Đọc dòng tóm tắt trước khi gõ Y: phải là 0 newly installed, 0 to remove. Hai câu hỏi tương tác có thể hiện ra giữa chừng:
- Hỏi về file
php.iniđã bị sửa: chọn 2 (giữ bản đang dùng). File này chứamemory_limit,upload_max_filesizemà bạn hoặc CyberPanel đã chỉnh. Bản vá nằm trong binary, không nằm trong php.ini. - Màn hình needrestart hỏi restart những service nào: chọn none of the above. Danh sách thường gồm cả MariaDB, Dovecot, SSH vì các lần cập nhật tự động trước đó. Restart hàng loạt giữa giờ làm việc gây gián đoạn không cần thiết.
Bước 3: khởi động lại PHP
pkill lsphp
systemctl restart lsws
systemctl restart lscpd
lscpd là tiến trình của chính giao diện CyberPanel (cổng 8090), cũng chạy PHP.
Bước 4: xác nhận
for b in /usr/local/lsws/lsphp*/bin/php; do echo "$b => $($b -v | head -1)"; done
ps -eo pid,lstart,cmd | grep '[l]sphp'
Kết quả đúng là các bản 8.2 trở lên đạt ngưỡng vá, ngày build là 21/10/2026, và các tiến trình lsphp có giờ khởi động sau lúc restart.
Các nhánh cũ trên CyberPanel
Kho LiteSpeed cũng phát hành bản build lại cho lsphp74, lsphp80 và lsphp81 (số revision tăng lên -21, ngày build tối 21/10), nhưng số version PHP giữ nguyên và gói không kèm changelog. Nhiều khả năng LiteSpeed đã đưa bản backport vào, nhưng chúng tôi không xác nhận được điều đó. Vì vậy với các nhánh này, chúng tôi vẫn cập nhật gói rồi áp thêm biện pháp tạm ở phần sau. Để biết site nào đang dùng nhánh cũ:
grep -lE 'lsphp(5|74|80|81)' /usr/local/lsws/conf/vhosts/*/vhost.conf
9. Vá trên máy chủ Docker
Với Docker, PHP nằm trong image chứ không nằm trên host. Chạy apt upgrade trên host không vá được container nào. Phải lấy image mới rồi tạo lại container.
Kiểm kê container chạy PHP
for c in $(docker ps -q); do
v=$(docker exec "$c" sh -c '(php -v || php-fpm -v) 2>/dev/null | head -1')
[ -n "$v" ] && printf '%s | %s | %s\n' "$(docker inspect -f '{{.Name}}' "$c")" "$(docker inspect -f '{{.Config.Image}}' "$c")" "$v"
done
Với container chưa đạt ngưỡng, xem PHP được lấy từ đâu:
docker exec <container> sh -c 'echo "PHP_VERSION=$PHP_VERSION"; head -2 /etc/os-release'
Biến PHP_VERSION có giá trị nghĩa là image dựa trên image chính thức php:*. Biến rỗng nghĩa là PHP được cài bằng apt hoặc apk bên trong image.
Cách vá theo từng loại image
| Loại image | Cách vá | Lưu ý |
|---|---|---|
Tự build FROM php:8.x-fpm hoặc php:8.x-apache | Ghim tag cụ thể như FROM php:8.3.36-fpm, rồi build lại với --pull --no-cache | Tag chưa có trên Docker Hub nghĩa là image chính thức chưa build xong |
| Image dựng sẵn của bên thứ ba (wordpress, nextcloud, bitnami…) | docker compose pull rồi up -d | Phụ thuộc vào việc nhà cung cấp đã build lại chưa |
| Dockerfile cài PHP bằng apt/apk | Build lại với --no-cache để lấy gói mới | Kiểm tra kho nguồn đã có bản vá trước khi build |
Image EOL (php:7.4, php:8.0, php:8.1, php:5.6) | Không có bản mới để kéo về | Chỉ còn biện pháp tạm và kế hoạch nâng nhánh |
Lệnh cho trường hợp tự build, kèm bước giữ image cũ để rollback:
docker tag <image_hiện_tại> <image_hiện_tại>-bak-$(date +%F)
docker compose build --pull --no-cache <service>
docker compose up -d <service>
--pull buộc tải base image mới. --no-cache tránh việc Docker dùng lại layer cũ còn chứa PHP cũ; thiếu cờ này, build xong vẫn có thể ra đúng image cũ.
Xác nhận
docker compose ps
docker exec <container> php -v | head -1
Cột CREATED phải là thời điểm vừa tạo lại. Chạy lại vòng kiểm kê cho toàn host để không sót container phụ như cron hay queue worker dùng chung image.
Nếu image được build qua CI rồi đẩy lên registry, phải build lại ở pipeline. Vá tay trên server rồi lần deploy sau kéo image cũ từ registry về là lỗi rất dễ xảy ra.
10. Khi chưa vá được: biện pháp tạm
Cách cộng đồng đang dùng là tắt tính năng theo dõi tiến trình upload: session.upload_progress.enabled = Off. Thiết lập này đóng được đường khai thác qua upload-progress, nhưng có thể không chặn hết cả hai lỗi vì bộ phân tích dữ liệu multipart vẫn bị chạm tới được. Quan điểm của nhóm PHP là cách giảm thiểu thật sự duy nhất vẫn là cập nhật.
Thực tế chúng tôi vẫn áp nó cho mọi nhánh EOL, kể cả khi gói đã được LiteSpeed build lại, vì chi phí gần như bằng không. Upload file vẫn chạy bình thường; chỉ ứng dụng nào đọc $_SESSION['upload_progress_*'] để vẽ thanh tiến trình upload là mất tính năng này.
Trên CyberPanel, áp cho các nhánh cũ (dùng find vì bản PHP cài tay có thể đặt php.ini ở chỗ khác):
for v in 5 74 80 81; do
find /usr/local/lsws/lsphp$v/etc -name php.ini -path '*litespeed*' 2>/dev/null
done | while read -r f; do
cp -p "$f" "$f.bak-$(date +%F)"
if grep -qE '^\s*;?\s*session\.upload_progress\.enabled' "$f"; then
sed -i -E 's/^\s*;?\s*session\.upload_progress\.enabled\s*=.*/session.upload_progress.enabled = Off/' "$f"
else
echo 'session.upload_progress.enabled = Off' >> "$f"
fi
echo "patched: $f"
done
pkill lsphp; systemctl restart lsws
Nếu một bản không in ra dòng patched:, chạy /usr/local/lsws/lsphpXY/bin/php --ini để biết nó đọc php.ini ở đâu.
Trên Docker, đưa thiết lập vào Dockerfile để nó tồn tại qua mỗi lần build:
RUN echo 'session.upload_progress.enabled=Off' > "$PHP_INI_DIR/conf.d/zz-php2shell.ini"
Hoặc mount file ini qua compose vào /usr/local/etc/php/conf.d/ (image chính thức). Đừng dùng docker cp, vì file sẽ mất khi container bị tạo lại.
Thiết lập này có thể bị bật lại ở cấp từng site qua .user.ini hoặc .htaccess. Rà lại bằng:
grep -rEil 'session\.upload_progress\.enabled' /home /var/www --include=.htaccess --include=.user.ini 2>/dev/null
Thêm một lớp nữa nếu site đi qua Cloudflare: bật Managed Ruleset, vì Cloudflare đã cập nhật luật WAF cho PHP2Shell từ ngày 21/10.
11. Những lỗi chúng tôi đã gặp
Lệnh nâng cấp đầu tiên chúng tôi chạy bị apt từ chối toàn bộ, kèm hàng loạt dòng E: Package 'lsphp83-gd' has no installation candidate. Nguyên nhân: dpkg-query -W 'lsphp*' liệt kê cả những gói dpkg chỉ biết tên mà chưa từng cài. Server không bị thay đổi gì, nhưng mất thêm vài phút. Lệnh ở trên đã lọc lấy riêng gói có trạng thái ii (đang cài) nên không còn lỗi này.
Các lỗi khác thì dễ đoán hơn nhưng vẫn hay gặp:
- Cập nhật gói xong mà quên
pkill lsphp. Version CLI báo đúng bản mới, trong khi worker phục vụ web vẫn chạy binary cũ. - Chọn “install the package maintainer’s version” ở câu hỏi php.ini. Cấu hình bị trả về mặc định, site có thể lỗi upload hoặc hết bộ nhớ.
- Chạy
apt upgradetoàn bộ vì thấy báo hơn trăm gói chờ cập nhật. Một máy của chúng tôi có 149 gói, gồm cả kernel và MariaDB. Đó là việc của một khung bảo trì khác. - Chỉ nhìn số version để kết luận. Gói lsphp80 sau khi cập nhật vẫn báo
PHP 8.0.30, giống hệt trước. Thứ thay đổi là ngày build. - Bỏ sót bản PHP cài ngoài trình quản lý gói, như một bản 5.6 build tay. Vòng kiểm kê theo thư mục bắt được nó, còn kiểm kê theo apt thì không.
- Trên Docker: build lại mà thiếu
--no-cache, hoặc vá trên server nhưng quên pipeline CI.
Một lỗi GPG từ kho của bên thứ ba (của chúng tôi là kho MaxScale của MariaDB) khi chạy apt update không cản trở việc vá. Apt chỉ bỏ qua kho đó và vẫn tải danh sách gói từ kho LiteSpeed.
12. Sau khi vá
Vá xong PHP là xong phần gấp. Phần còn lại không cần làm trong đêm nhưng không nên để quá vài tuần.
- Reboot các máy đang chờ kernel mới, trong khung bảo trì ngoài giờ. Reboot cũng là cách gọn nhất để các service dùng thư viện cũ nạp lại, thay cho màn hình needrestart đã bỏ qua lúc vá.
- Lập danh sách site còn chạy PHP 8.1 trở xuống và lịch nâng nhánh cho từng site. Với site PHP 5.6, biện pháp tạm chỉ giảm rủi ro; nên đặt sau WAF hoặc giới hạn truy cập nếu là hệ thống nội bộ.
- Lên kế hoạch cho các site đang dùng PHP 8.2, nhánh này hết hỗ trợ bảo mật ngày 31/12/2026.
- Xem lại log truy cập từ 20/10 tới thời điểm vá, chú ý các POST dạng multipart bất thường tới những trang vốn không có chức năng upload.
- Cập nhật lại Dockerfile và pipeline CI để lần build sau không kéo về base image cũ.
Điều chúng tôi chưa chắc nhất là các gói lsphp74, lsphp80, lsphp81 mà LiteSpeed build lại. Thời điểm build trùng khớp với đợt vá, nên rất có thể bản backport đã nằm trong đó. Nhưng khi không có changelog thì “rất có thể” chưa đủ để bỏ biện pháp tạm. Nếu LiteSpeed công bố xác nhận, chúng tôi sẽ cập nhật bài này.
Nếu bạn quản lý nhiều máy chủ, cách làm nhanh nhất là chạy vòng kiểm kê ở bước 1 trên tất cả máy trước, dồn kết quả vào một bảng, rồi mới vá lần lượt. Ba VPS của chúng tôi mất chưa tới một buổi sáng theo cách đó, kể cả thời gian xử lý các lỗi kể trên.
Nguồn tham khảo
- php.announce: Upcoming Critical PHP Security Release
- PHP: News Archive 2026
- PHP: Supported Versions
- Help Net Security: PHP2Shell patched
- The Hacker News: PHP issues emergency patches
- BleepingComputer: PHP warns admins of two critical flaws
- ma.ttias.be: How to apply the patches
- Cody Kretsinger: package status timeline
- DEV Community: versions, risk by SAPI, stopgaps
- Threat Landscape: PHP core RCEs leak ahead of embargo
- Wordify: live updates
- GitHub ersinkoc/php-fix
- LiteSpeed: LSPHP getting started