一句話直答:這不是某個框架或外掛的 bug,而是 PHP 核心在「發生致命錯誤時怎麼收尾」的設計缺陷,可觸發的程式碼最早可追溯到 2012 年的 PHP 5.4。要確認自己是否受影響,不能只看 php -v 開頭的數字,要看發行版套件的版號、以及真正在回答網頁請求的那個 SAPI。
上一篇談危害,這篇談追蹤。看懂編號體系之後,你在下一次重大漏洞時可以自己判斷,不必等別人餵結論。
漏洞從哪來:兩個被打破的假設
兩個 CVE 共用同一個根因:PHP 用 longjmp() 處理致命錯誤,直接拋棄執行現場,然後進入一段假設「所有資料結構都完整」的清理流程。細節分別落在兩個不同的地方:
- CVE-2026-109618(記憶體耗盡路徑):與請求解析、multipart 處理以及 session 上傳進度(
ext/session的 upload progress 回呼)有關。研究指出其中一個前提來自 2017 年 10 月的效能優化,首次出貨於 2018 年 12 月的 PHP 7.3.0,改變了雜湊表的排列順序,讓「標記了項目但記憶體未配置」的狀態變得可被外部操控。 - CVE-2026-109619(致命錯誤與殘留狀態路徑):致命錯誤回溯(fatal error backtrace)與跨請求的模組級全域狀態。相關的序列化與 session 程式路徑可以再往前追到 PHP 7.1 與 PHP 5.4。官方公告記錄了一條已驗證的 PHP-FPM 利用路徑。
另外值得記一筆的是發現方式:多家媒體報導這兩個漏洞是在 AI 協助下找出來的,評級 CWE-824、CVSS v4.0 9.2。它提醒我們一件事,長年潛伏的記憶體問題不會因為「大家用了十年沒事」就自動變安全。
同一件事,四種編號:各自代表誰在負責
新手最常卡住的不是技術,是「這麼多號碼到底哪個算數」。答案是:它們負責的交付鏈不同。
| 體系 | 誰發布 | 回答什麼問題 | 這次的值 |
|---|---|---|---|
| CVE | MITRE/CVE.org | 全球統一的漏洞身分證,跨廠商對照用 | CVE-2026-109618、CVE-2026-109619 |
| GHSA | GitHub Advisory(PHP 專案在 php/php-src 的 security advisories 發布) | 上游開發者自己怎麼描述、影響範圍與修補提交 | GHSA-w8hw-w9fx-j79w、GHSA-6wmf-4rv5-p3rp |
| USN/DSA/DLA/RHSA | Ubuntu/Debian/Red Hat 等發行版 | 「你機器上裝的那個套件」什麼版本才是修好的 | USN-8948-1、USN-8948-2 等 |
| 上游 release 與分支 | PHP 專案(php.net 與 php-src) | 原始碼層級的修補點,以及沒有正式版的分支怎麼辦 | 8.5.12/8.4.27/8.3.36/8.2.35 |
為什麼要有四層?因為從原始碼到你的機器之間至少有兩層轉手:上游給你原始碼,發行版或控制面板(cPanel、寶塔、Docker 映像)給你實際安裝的東西,你的服務商再幫你決定能不能更新。任何一層沒動,漏洞就還在。所以專業的追蹤習慣是「用 CVE 編號橫向對照每一層」,而不是只讀一則新聞。
怎麼自己判斷手上版本是否受影響
- 列出所有 PHP 執行環境,先確認哪一個在服務網站。CLI 的版本往往和 php-fpm 不同,這是誤判的最大來源。
- 對照修補版清單:8.5 需 8.5.12、8.4 需 8.4.27、8.3 需 8.3.36、8.2 需 8.2.35;低於這些數字就受影響。8.1、8.0、7.4 及更舊沒有正式修補版。
- 看發行版套件版號,不要套上游版號。Ubuntu 的修補是以套件形式進到既有版本號裡,同一台機器上「看起來很舊」的版號其實已修好。
- 確認修補後的二進位真的被載入,且 worker 已重啟。換了檔案卻沒重啟 PHP-FPM 或網頁伺服器,等於沒修。
# 一、列出所有已安裝的 PHP 套件與版本(Debian/Ubuntu)
dpkg -l 'php*' | awk '/^ii/{print $2, $3}'
apt list '?installed ?name(^php[0-9.]+$)' # Ubuntu 官方建議的寫法
# 二、RHEL 系
rpm -qa 'php*' | sort -V | tail -20
# 三、正在服務的執行檔與啟動時間(重啟過才會有新的時間)
ls -l /proc/$(pgrep -o php-fpm)/exe
ps -o lstart= -p $(pgrep -o php-fpm)
# 四、哪個 ini 真的被載入、關鍵設定目前是什麼
php --ini | head -5
php -r 'echo "upload_progress=", ini_get("session.upload_progress.enabled"), " post_max_size=", ini_get("post_max_size"), PHP_EOL;'
關於第三步的陷阱,具體一點說:Ubuntu 24.04 的 php8.3 修補版版號是 8.3.6-0ubuntu0.24.04.13,22.04 的 php8.1 是 8.1.2-1ubuntu2.28。如果你拿「8.3.36」去 grep,會得出「還沒修」的錯誤結論;反過來,如果在更新的機器上只看 php -v 前三個數字,也可能誤以為自己修好了。正確做法是打開發行版的公告頁,或查套件的 changelog。
EOL 分支:7.4/8.0/8.1 的「官方分支」是什麼意思
PHP 專案已不為這些分支發布正式版本,這次因為嚴重程度例外提供了 minimal source backports,分支名稱帶有 -CVE-2026-109618-109619 後綴(例如 PHP-7.4-CVE-2026-109618-109619)。重點在於:
- 它只對自行編譯的人有用,不會變成一般套件更新,也不代表這些分支恢復常規支援。
- 它的定位是「給沒有維護廠商、又必須先撐住的人一條路」,不是長期方案。
- 分支上的版本號可能顯示為開發版(例如 7.4 分支在編譯時顯示為 7.4.34-dev 這類字樣),別拿它去跟正式版號硬比。
除了官方回移植,還有幾條路:發行版的延長支援(Ubuntu 20.04 的 php7.4 修補在 USN-8948-2,需要 Ubuntu Pro/ESM)、Debian 的付費 ELTS、RHEL 是否回移植要逐一套件確認、控制面板(cPanel 的 EasyApache 有 ea-php7.4/8.0/8.1 的修補版)、以及社群自行編譯的 Docker 映像。最後一種要特別小心:社群映像方便,但沒有經過 PHP 專案審核,用之前請確認它的 patch 來源與版本一致性。
五個查證習慣
- 三方交叉:上游 release 公告、php-src 的 GHSA、你的發行版 USN/DSA,三個都看過再下結論。
- 用編號去找,不要用新聞去找:把 CVE 編號丟進發行版的漏洞追蹤頁,比讀十篇轉貼快。
- 看誰簽名:官方公告、發行版公告、廠商部落格的可信度不同,轉貼文只當線索。
- 記錄查詢日期與來源網址:漏洞資訊一週內會更新好幾版(修補版號、影響範圍、緩解有效性都可能改)。
- 把結論寫進資產清單:哪台機器、哪個版本、什麼時候升、誰驗收。三個月後你會感謝現在的自己。
常見問題
我只要記住「升到 8.3.36 就好」嗎?
上游層面可以這樣記,但實務上不夠。你要記的是「我的交付管道把修補送到了哪個版號」,因為套件、面板與 Docker 映像各有自己的版號規則。
沒有正式修補版的 7.4,還有人提供修補嗎?
有,來源分三類:PHP 專案自己的原始碼回移植分支、發行版或廠商的延長支援(多為付費),以及社群自行編譯的映像。前兩類可以查 patch 與公告,第三類要自己驗證。
我看的是 CLI 版本,這樣夠嗎?
不夠。網站跑的是 FPM 或 mod_php,兩者的設定與 binary 可能不同。至少要看一次 /proc/<pid>/exe 指向哪一支執行檔。
接下來看這兩篇
- PHP2Shell 是什麼?兩個 9.2 分 RCE 的危害與攻擊面:成因、攻擊鏈、不修的後果與過渡緩解。
- PHP2Shell 修補與實戰升級 SOP:含我們在寶塔多版本環境實際踩到的三個坑與驗收標準。
把上面的四步檢查跑完,你手上就會有一張「機器對應 PHP 版本」的表,那張表在下次漏洞來臨時可以直接重複使用。如果追蹤過程中遇到版號看起來很舊、但其實已經修好的情況,歡迎留言貼出來,讓其他人少踩一次同樣的坑。


