查看目前的 session 設定
修改前先看一次目前的值,之後可以和第 5 步的結果比對。
sudo php-fpm8.4 -i | grep session
重點看 session.upload_progress.enabled 和 session.use_strict_mode 這兩行。
更新 php ini
新增一個緩解設定檔。conf.d 裡的檔案會被 FPM 自動載入,檔名用 99- 開頭讓它最後載入,覆蓋前面的設定。
sudo vi /etc/php/8.4/fpm/conf.d/99-fix-php2shell.ini
; Fix CVE-2026-109618 / 109619 (2026-10-21) session.upload_progress.enabled = 0 session.use_strict_mode = 1 expose_php = Off
更新 php-fpm pool 設定
在 pool 設定裡用 php_admin_flag 和 php_admin_value 鎖住這些設定,網站程式就無法再自行改回來。
sudo vi /etc/php/8.4/fpm/pool.d/www.conf
; Fix CVE-2026-109618 / 109619 (2026-10-21) php_admin_flag[session.upload_progress.enabled] = off php_admin_flag[session.use_strict_mode] = on
upload_max_filesize 自動算成 30M(post_max_size × 0.95,無條件捨去)
; Fix CVE-2026-109618 / 109619 (2) (2026-10-22) php_admin_value[memory_limit] = -1 php_admin_value[post_max_size] = 32M php_admin_value[upload_max_filesize] = 30M
檢查並套用
先用 -t 檢查設定語法,通過後再 reload。reload 會平滑重載 worker;設定沒有生效時再改用 restart。
-
檢查設定語法
sudo php-fpm8.4 -t -
查看 session 相關設定
sudo php-fpm8.4 -i | grep session -
檢查通過後 reload
sudo php-fpm8.4 -t && sudo systemctl reload php8.4-fpm
-
檢查通過後 restart(reload 沒生效時用)
sudo php-fpm8.4 -t && sudo systemctl restart php8.4-fpm
-
查看服務狀態
sudo systemctl status php8.4-fpm
檢查 PHP-FPM
不經過網站,直接用 cgi-fcgi 連到 FPM 的 socket 執行一支暫存的 PHP 檔,列出這個 pool 實際生效的設定,包括 pool 裡的 php_admin_flag 和 php_admin_value。跑完會刪掉暫存檔並移除 libfcgi-bin。
function check_fpm_via_cgi {
sudo apt install -y libfcgi-bin # 沒裝的話
sudo tee /tmp/test-php-2f67c46f.php >/dev/null <<'EOF'
<?php
$os = @parse_ini_file('/etc/os-release')['PRETTY_NAME'] ?? '?';
echo "OS : $os\n";
echo "PHP : ", PHP_VERSION, " (", PHP_SAPI, ")\n";
echo "php.ini : ", php_ini_loaded_file(), "\n";
echo "user : ", function_exists('posix_geteuid') ? posix_getpwuid(posix_geteuid())['name'] : get_current_user(), "\n\n";
foreach ([
'memory_limit','post_max_size','upload_max_filesize','session.upload_progress.enabled',
'session.use_strict_mode','expose_php',
'max_input_vars','max_input_nesting_level','max_file_uploads','max_execution_time',
'display_errors','display_startup_errors','log_errors','error_reporting',
'open_basedir','disable_functions','allow_url_fopen','allow_url_include','opcache.enable',
] as $k) {
$v = ini_get($k);
printf("%-34s %s\n", $k, $v === false ? '(n/a)' : ($v === '' ? '(empty/off)' : $v));
}
EOF
sudo env SCRIPT_FILENAME=/tmp/test-php-2f67c46f.php REQUEST_METHOD=GET cgi-fcgi -bind -connect /run/php/php8.4-fpm.sock
sudo rm /tmp/test-php-2f67c46f.php
sudo apt purge -y libfcgi-bin
}
check_fpm_via_cgi
history -c
socket 路徑用的是 Debian/Ubuntu 預設的 /run/php/php8.4-fpm.sock,pool 的 listen 改過的話要換成實際路徑。主機原本就裝了 libfcgi-bin 的話,記得拿掉 apt purge 那一行。最後的 history -c 會清掉目前 shell 的指令紀錄。
重點看前六項:memory_limit 是 -1,post_max_size 是 32M,upload_max_filesize 是 30M,session.use_strict_mode 是 1,session.upload_progress.enabled 和 expose_php 是 (empty/off) 或 0。
重新啟動 PHP-FPM
收尾時重新啟動一次 PHP-FPM。指令會先用 -t 檢查設定,通過才會 restart。
sudo php-fpm8.4 -t && sudo systemctl restart php8.4-fpm
觀察 FPM 記憶體用量
memory_limit 設成 -1 之後,單一請求不再有記憶體上限。重新啟動後可以用這行看每個 FPM 程序佔用的記憶體,依 RSS 由大到小排序,只列前幾筆。
ps -o pid,rss,cmd -C php-fpm8.4 --sort=-rss | head
PID RSS CMD 27951 30904 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf) 27974 20260 php-fpm: pool www 27987 14852 php-fpm: pool www 27988 14852 php-fpm: pool www 27989 14852 php-fpm: pool www 27973 14848 php-fpm: pool www 27975 14848 php-fpm: pool www 27976 14848 php-fpm: pool www 27977 14848 php-fpm: pool www
RSS 的單位是 KB。範例裡 master 約 30 MB,每個 www worker 約 15–20 MB。某個 worker 明顯比其他大很多時,可以從它的 PID 追查是哪個請求吃掉記憶體。
升級到修補版
設定緩解只是暫時擋住,升級 PHP 才是正式修補。修補版由 ondrej/php PPA 提供,只有 Ubuntu 22.04 和 24.04 拿得到;18.04 和 20.04 的 PPA 已經停止更新,只能繼續靠上面的設定緩解。
PHP 8.4 的修補版是 8.4.27-1 以後的版本,完整版本號後面還會接 +ubuntu24.04.1+deb.sury.org+1 這類字尾。
-
更新套件清單
sudo apt update
-
確認 Candidate 是修補版
apt-cache policy php8.4-fpm -
記下目前載入的模組
php8.4 -m > ~/php-mods-before.txt -
備份設定目錄
sudo tar czf ~/php8.4-etc-$(date +%F).tgz /etc/php/8.4
-
模擬升級,不會真的安裝
sudo apt install --only-upgrade -s 'php8.4-*'
Candidate 還不是修補版,代表 PPA 還沒上架,這時升級拿不到這次的修補。模擬結果裡一大串 Skipping ..., it is not installed 可以忽略,要看的是最後會升級哪些套件,以及是不是 0 newly installed, 0 to remove。
sudo apt -o Dpkg::Options::="--force-confold" install --only-upgrade 'php8.4-*'
同一個小版本裡升級,模組不用重裝,conf.d/99-fix-php2shell.ini 也不會被動到。--force-confold 會讓改過的 www.conf 保留你的版本;沒加這個參數時,如果被問到要不要換,選 N。
-
確認套件版本
dpkg-query -W -f='${Version}\n' php8.4-fpm -
比對升級前後的模組
php8.4 -m | diff ~/php-mods-before.txt - && echo "模組都一樣" -
找出新版範本檔(有的話代表新套件改過範本,你的設定仍保留)
sudo find /etc/php/8.4 -name '*.dpkg-*' -o -name '*.ucf-*' -
確認 pool 設定還在
grep -n 'php_admin' /etc/php/8.4/fpm/pool.d/www.conf -
檢查設定語法
sudo php-fpm8.4 -t
7.2 到 8.1 的修補是回移植進舊版本,php -v 顯示的版本號不會變,要用上面的 dpkg-query 看套件版本。最後再跑一次第 6 步,確認 FPM 實際用到的值。