Featured image of post PHP 重大漏洞 CVE-2026-109618/CVE-2026-109619:修補路徑與無法升級時的緩解

PHP 重大漏洞 CVE-2026-109618/CVE-2026-109619:修補路徑與無法升級時的緩解

PHP 官方於 2026 年 10 月 21 日公告兩個 CVSS 9.2 的遠端程式碼執行漏洞。本文整理影響範圍、官方修正版本、發行版與面板的修補方式,以及 PHP 7.4/8.0/8.1 這類沒有官方版本時,可以先落地的設定緩解與驗證方法。

最後更新
約 3498 字

PHP 官方在 2026 年 10 月 21 日發布安全公告,一次揭露兩個重大遠端程式碼執行(RCE)漏洞:CVE-2026-109618 與 CVE-2026-109619。兩者在 CVSS v4.0 都是 9.2,官方的建議只有一句:立刻更新。

這篇整理我們實際處理這兩個 CVE 時的判斷與做法:哪些版本受影響、該升到哪一版、發行版與主機面板怎麼修,以及 PHP 7.4、8.0、8.1 這類官方不再出版的版本,在升級之前能先做什麼。文中不含任何利用方式,也不討論攻擊手法。

兩個 CVE 是什麼

編號官方公告問題性質
CVE-2026-109618GHSA-w8hw-w9fx-j79w記憶體耗盡(OOM)處理路徑造成狀態損毀,進而導致 RCE
CVE-2026-109619GHSA-6wmf-4rv5-p3rp請求之間殘留過期的全域狀態,進而導致 RCE

兩者的官方修補說明是同一句:避免在 bailout 之後狀態被破壞(Avoid state corruption via bailout)。

重點在影響面。凡是用 PHP 處理 Web 請求的部署都在範圍內:PHP-FPM、mod_php、php-cgi、FrankenPHP、LiteSpeed 皆然。其中 mod_php 風險最高,因為公開資料指出問題可在應用程式程式碼執行之前、請求初始化階段就觸發,不需要網站本身有任何漏洞。只提供命令列使用(CLI)而不接 Web 請求的 PHP,實際曝險低很多,但仍建議一併更新。

影響版本與官方修正版本

官方修正版本只涵蓋仍在支援期的分支,更新日期為 2026 年 10 月 22 日:

分支修正版本
PHP 8.58.5.12
PHP 8.48.4.27
PHP 8.38.3.36
PHP 8.28.2.35
PHP 8.1 及更舊沒有官方版本

8.1 的最後一版是 2025 年 12 月的 8.1.34,之後不會再出版。官方對 7.4、8.0、8.1 提供的是最小範圍的原始碼 backport,供自行編譯或由發行版、長期支援廠商吸收。換句話說,這些版本能不能被修好,取決於你用的套件來源有沒有跟進。

第一步:先盤點,不要只看 CLI 版本

這次最容易出錯的是「以為升級了」。一台主機上常有多組 PHP:

  • 系統預設的 php 指令是 CLI,版本號不代表 FPM 版本。
  • 使用第三方套件庫(例如 Sury)的主機,可能同時裝了多個分支,每個分支各有自己的 FPM 與 pool。
  • 主機面板(例如 DirectAdmin CustomBuild)自行編譯的 PHP,與系統套件是兩套東西,apt upgrade 不會動它。

我們的做法是逐台列出實際提供 Web 服務的 PHP 版本,再對照 pool 與站點。唯讀盤點可以回答三件事:每個站點實際跑哪個分支、該分支有沒有官方修正版、更新後要重啟哪些服務。

判斷「修好了沒有」不能只看版本字串。尤其是發行版套件,版本號常常只是小幅上升,要看 changelog 有沒有明確列出這兩個 CVE,或用安全追蹤頁確認修正版本。後面會舉一個實際遇到的例子。

我們採用的修法

能升級的:用套件或面板升到官方修正版

  • Debian 系統套件:Debian 已發布修正,bookworm 的 php8.2 為 8.2.35-1~deb12u1,trixie 的 php8.4 為 8.4.27-1~deb13u1。只升級已安裝的 php* 套件即可,不需要整機升級。
  • Sury 套件庫的多版本 PHP:8.2 升到 8.2.35、8.3 升到 8.3.36、8.4 升到 8.4.27、8.5 升到 8.5.12。
  • 面板自行編譯的 PHP:只重建 PHP,不重建 Web 伺服器。重建前先備份選項檔、版本紀錄與目前的 PHP 目錄,重建後確認模組清單與重建前一致。

更新套件時我們用的原則是:

  1. 只動 PHP 相關套件,並指定只升級不新裝(--only-upgrade),設定檔衝突時保留既有設定。
  2. 升級前先存一份目前的 PHP 套件清單,作為回滾依據。
  3. 升級後重啟所有 FPM 實例,再重載 Web 伺服器。只升級套件而不重啟,舊的 worker 仍在記憶體裡跑舊程式碼,這點很容易漏。
  4. 逐站做煙霧測試,並與升級前的狀態對照。升級前就是 403、525 的站點,升級後仍是 403、525 才算沒有變動,不要把既有的狀態誤判成這次造成的問題。

一個容易誤判的例子:版本號上升不代表已修補

Sury 套件庫的 PHP 5.6 在這次更新後,changelog 明確寫了 backport 自 8.2.35 並列出兩個 CVE,這可以視為已修補。同一次更新裡,PHP 8.1 也從 8.1.34-8 升到 8.1.34-9,但 changelog 完全沒有提到這兩個 CVE。

所以 8.1 即使「已更新到最新套件」,仍然要當作未修補,必須走下一節的緩解。這種情況只能靠讀 changelog 或安全追蹤頁判斷,不能用版本號上下猜。

無法升級時:PHP 7.4、8.0、8.1 的緩解

官方在公告中給了暫時性的緩解設定,同時明確說明這些不是修補,不能讓安裝變得安全,只是降低風險。我們對仍在使用 PHP 7.4 與 8.1 的環境,是這樣落地的。

針對 CVE-2026-109619

停用 session 上傳進度功能:

1
session.upload_progress.enabled = Off

有兩個細節:

  • 要設在 php.ini 或 FPM pool 設定裡,用 pool 的 php_admin_flag 鎖定。官方特別指出用 ini_set 或 .user.ini 不算數,因為那些是應用程式或使用者可以自行改動的層級。
  • 改完要重啟所有 worker 才會生效。

PHP 8.5 另有一項緩解是關閉 fatal_error_backtraces 並重啟。我們沒有 8.5 的 Web 服務,所以這項只列在文中供參考。

針對 CVE-2026-109618

這個漏洞與記憶體耗盡的路徑有關,緩解的方向是讓請求不容易走到 OOM:

  • 限制 post_max_size:不需要上傳的站點用 8M,需要上傳的用 32M 左右,並讓 upload_max_filesize 小於 post_max_size。
  • 在 Web 伺服器或反向代理層另外限制請求大小與請求數量。
  • 用 cgroup 限制行程的實體記憶體。官方特別註明不要用 RLIMIT_AS、RLIMIT_DATA 這類位址空間限制來代替。
  • 官方列出的另一個選項是用不可覆寫的方式把 memory_limit 設為 -1。這個做法有明顯的副作用(單一請求可以吃光主機記憶體),除非有 cgroup 這類外部上限,否則我們不建議單獨採用。
  • 把 memory_limit 以 php_admin_value 固定,避免被 .user.ini 或 ini_set 改掉。

設定放哪裡才有效

我們把緩解寫在兩個層級,互相補強:

  1. 全域 ini:放進該版本 PHP 的額外設定目錄,新增一個獨立檔案(例如以 CVE 編號命名),內容只有上述三到四個設定。獨立檔案的好處是回滾只要刪檔,不會污染原有的 php.ini。
  2. FPM pool:在每個 pool 以 php_admin_flag/php_admin_value 寫入 session.upload_progress.enabled、post_max_size、upload_max_filesize,並把該 pool 目前實際生效的 memory_limit 原樣寫成 php_admin_value,不要因為加了鎖定而意外改變行為。

改之前務必備份原設定檔,並用 php-fpm -t 之類的語法檢查通過再重啟。

上傳大小的代價要先講清楚

緩解會有實際的功能影響。我們有一個站點原本把上傳上限放寬到數百 MB,套用後變成約 30 MB,超過的上傳會失敗。這類站點需要事先通知,或改用分段上傳、直傳物件儲存等方式。與其事後被客訴,不如在套用前就把影響範圍告訴站點負責人。

面板會改寫你的設定

使用面板管理 PHP 時要特別留意:面板在重寫設定或重建 PHP 時,可能重新產生 pool 設定與 php-fpm.conf,你手動加進去的鎖定值有被覆蓋的風險。獨立的 ini 檔通常能保留,但如果沒有在 pool 層級用 php_admin_* 鎖定,仍可能被 .user.ini 覆蓋。我們的做法是把「面板重寫設定後要重新檢查緩解值」記在維運待辦裡,每次面板操作後重新驗證一次。

驗證:看實際生效值,不要看設定檔

改設定最常見的失誤是「檔案寫了,但實際沒生效」。驗證時要回答的是每個 pool 實際跑的值:

  • session.upload_progress.enabled 是否為關閉
  • post_max_size、upload_max_filesize、memory_limit 是否為預期值
  • 實際執行的 PHP 版本是否為預期版本

要注意,在命令列執行 php -i 看到的是 CLI 的設定,不等於 FPM pool 的設定。我們是對每個 pool 的 FastCGI socket 做一次唯讀的設定查詢,逐 pool 對照上面幾個值。

另外做了兩件輔助確認:

  • 官方修正版的二進位在版本資訊之外,也能用它是否包含修正後新增的行為特徵來交叉確認;面板編譯的 PHP 也確認有套用對應的 CVE 修補檔。
  • 站點層面逐一確認回應碼,與升級前對照。

我們沒有對任何正式站執行公開流傳的利用程式。這類程式可能觸發記憶體耗盡甚至實際取得執行權限,不適合拿來驗證正在營運的系統。等效的做法是檢查版本、修補特徵與生效設定,這樣已經足以判斷是否曝險,又不會留下風險。

建議的處理順序

給需要自己跑一輪的人,大致可以這樣排:

  1. 盤點所有對外提供 PHP 的主機,包含系統套件、第三方套件庫、面板編譯三種來源。
  2. 能升級的先升級到 8.2.35、8.3.36、8.4.27、8.5.12 或發行版對應的修正版,並重啟所有 FPM。
  3. 無法升級的(7.4、8.0、8.1)先確認套件來源有沒有 backport;沒有的話套用上述緩解,同時規劃遷移到仍在支援的分支。
  4. 逐 pool 驗證實際生效值,逐站做回應碼檢查並與升級前對照。
  5. 把面板重寫設定、之後新增的 pool 這些會讓緩解失效的情況列入後續檢查。
  6. 在 Web 伺服器、反向代理或 CDN 層,限制請求大小與速率,作為多一層保護。

結論

這次的修補本身不複雜,難的是「哪些 PHP 真的被修好了」。同一台機器上的 CLI、多個 FPM 分支、面板編譯版本、第三方套件庫,每一種來源的更新路徑與判斷方式都不同;版本號上升也不保證已經包含修補。

對無法升級的舊版本,上面的設定只能降低風險,不能取代升級。這類站點最後還是要排進遷移計畫,改到仍受官方支援的分支,避免下次又要再面對一次「沒有官方版本可用」。


使用 Hugo 建立
主題 Stack 由 Jimmy 設計