---
title: "PHP2Shell 漏洞成因與修補指南"
description: "解析 PHP2Shell 的兩類生命週期缺陷，整理運行時升級、暫時緩解、補丁選擇與實際 Web 鏈路驗收方法。"
language: "zh-Hant"
url: "https://keendigit.com/zh-hant/insights/php2shell-remediation-guide"
author: "KeenDigit"
published: "2026-10-22"
---

# PHP2Shell 漏洞成因與修補指南

解析 PHP2Shell 的兩類生命週期缺陷，整理運行時升級、暫時緩解、補丁選擇與實際 Web 鏈路驗收方法。

**資料核驗截至：2026 年 10 月 22 日** **適用對象：PHP 應用維、安全回應人員，以及維護 PHP 自編譯版本的工程師。**

本文整理 PHP2Shell 的漏洞成因、影響範圍、正式修復流程、臨時緩解措施與官方修補程式實現。正文使用 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1) 等編號引用；全部來源連結集中列於文末附錄。配置片段是部署模板，需結合實際版本、業務容量和配置繼承關係調整。

## TL;DR：修復步驟與建議

1. **升級 PHP 運行時**：對應分支至少升級至 **8.2.35、8.3.36、8.4.27 或8.5.12**；使用發行版軟體套件時，以廠商確認同時修復兩個 CVE 的完整套件版本為準。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S10](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-10)
2. **取代全部舊進程**：升級後重新啟動或捲動取代所有 PHP worker、承載 PHP 的服務及容器，確認舊實例已退出。
3. **從實際 Web 連結驗收**：核對 Web SAPI、完整軟體包版本和運行實例；僅檢查 `php -v` 不足以證明線上已修復。
4. **做業務回歸並恢復正常預算**：檢查登入、session、上傳、匯入及錯誤處理；若緊急時取消 PHP 記憶體上限，修復後恢復適當的有限預算。
5. **暫時無法升級時**：優先在 PHP 之前限制不可信流量；按第 5 節評估關閉 upload progress、PHP 8.5 fatal backtrace 等措施。所有配置緩解和 WAF 均有覆蓋邊界，不能取代升級。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

## 1. 漏洞概覽與風險判斷

PHP2Shell 在本文中指 2026 年 10 月 21 日 PHP 官方揭露的兩個 Critical 等級漏洞。兩者都與 PHP 引擎的記憶體和請求生命週期管理有關，存在未認證遠端程式碼執行風險。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

| 專案          | CVE-2026-109618          | CVE-2026-109619            |
| ----------- | ------------------------ | -------------------------- |
| 官方名稱        | RCE via OOM corruption   | RCE via stale global state |
| 核心問題        | 記憶體不足導致異常跳轉，留下尚未完成初始化的狀態 | worker 中殘留指向已釋放請求記憶體的全域狀態  |
| 典型發生時機      | 目前請求的初始化、執行或清理過程         | 前一請求留下狀態，後續請求提前消費          |
| OOM 是否為必要條件 | 屬於漏洞核心觸發機制               | 不是；其他致命錯誤及清理後期診斷也可能參與      |
| 根本修復方向      | 安全處理分配失敗與請求終止            | 修正狀態所有權、清理時機與提前初始化         |
| 處置要求        | 必須修復                     | 必須同時修復                     |

依據：兩份官方安全公告及修復提交。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)[S4](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-4)

### 1.1 受影響部署應如何理解

PHP 官方將 **所有處理 Web 請求的 PHP 部署** 列入風險範圍，包括 PHP-FPM 、 Apache mod\_php 、 php-cgi 、 FrankenPHP 和 LiteSpeed 。已示範的 mod\_php 攻擊可以發生在應用程式碼執行之前，因此僅依賴 PHP 應用程式中的登入檢查、框架中間件或上傳校驗，並不能覆寫這種路徑。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)

需要區分「部署需要修復」與「某一攻擊鏈已完整證明」。 CVE-2026-109618 的公告說明：FPM 在請求啟動失敗後會退出子進程，阻斷了 mod\_php 對應的啟動失敗後清理路徑；但啟動成功後的 OOM 路徑仍存在風險。該公告同時註明，針對此 CVE 的完整 FPM 利用尚未展示。這個限制不能據此推導出 FPM 安全，尤其不能忽略 CVE-2026-109619。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

成功利用的直接權限邊界取決於承載 PHP 的進程身分及其可存取資源。通常應專注於網站程式碼、上傳目錄、資料庫憑證、服務令牌和內部網路存取能力；「遠端程式碼執行」不等於天然取得 root 權限。這裡的後果判斷是基於進程權限模型，實際影響需要結合部署權限評估。

一般一次性 CLI 腳本不具備相同的 HTTP 入口；但以 CLI 或嵌入方式長期處理外部任務的進程，仍應納入運行時與生命週期盤點。只更新 CMS、框架或 Composer 依賴，也不會自動取代底層 PHP 引擎。

## 2. 成因分析

### 2.1 先理解兩個生命週期

PHP worker 往往連續處理多個請求。請求期間分配的記憶體可以在請求結束時統一釋放，而 worker 本身及其部分全域欄位繼續存在。

因此，引擎必須維持兩項限制：

- **初始化約束**：對其他程式碼可見的數據，必須處於可安全讀取、遍歷和銷毀的狀態。
- **生命週期約束**：請求記憶體釋放後，存活更久的欄位不能繼續把其中的位址當成有效狀態。

這兩項限制分別對應兩組漏洞的主要失敗方式。以下流程是結合公告與修補程式整理的機製說明，不代表每個部署都存在完全相同的可達路徑。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)[S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

### 2.2 CVE-2026-109618：OOM 打斷了尚未完成的狀態更新

舊實作使用 `longjmp()` 一類非局部跳轉來處理 OOM，相關路徑透過 `zend_bailout()` 退出目前執行上下文。危險在於，一段 C 程式碼可能已經將新物件、陣列或請求狀態發佈給其他程式碼，但尚未完成全部欄位初始化；此時任意一次相關時機上的分配失敗，都可能使正常的收尾步驟被跳過。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

可以把失敗過程拆成四個步驟：

1. 建立或更新請求內部結構，並使其可存取。
2. 後續記憶體分配失敗，觸發 OOM。
3. 執行流跳離目前函數，原本用於完成初始化或恢復狀態的程式碼沒有執行。
4. 請求清理繼續處理這些結構，將無效內容當作有效欄位或位址。

這裡的關鍵不是“內存用完就一定產生 RCE”，而是**內存不足改變了控制流，破壞了引擎對結構有效性的假設**。失敗的分配也不必與最終被錯誤讀取的結構直接相關。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

#### 為什麼較小的請求也可能耗盡內存

請求體位元組數與解析後的堆佔用不是一回事。一個欄位在 PHP 內部可能對應多個字串、陣列元素和元資料物件；輸入的結構複雜度會影響記憶體放大程度。

官方公告列出的 multipart 問題包括：缺少可用聲明長度時的初始大小檢查缺口、單個 part 的頭部數量未受到充分限制，以及空文件控制項仍產生元資料、嵌套名稱進一步增加數組工作量。應用自身對輸入的展開、解碼或重複分配，也可能成為 OOM 來源。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

由此可得兩條防護結論：

- 請求體限制必須盡量在進入 PHP 前執行，並考慮實際讀取長度與結構複雜度。
- 單獨限製檔案大小、檔案數量，或只關閉一個上傳入口，無法覆蓋所有 OOM 來源。

#### 為什麼應用鑑權可能來不及

在 mod\_php 中，請求初始化階段就可能自動解析請求體；即使啟動失敗，相關請求清理仍會執行。已確認攻擊路徑因此可以先於應用程式碼發生。若要在這個階段減少暴露，限制需要放在反向代理、Web 伺服器或其他位於 PHP 請求處理之前的邊界。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

### 2.3 CVE-2026-109619：請求記憶體已釋放，全域引用仍存活

這問題涉及錯誤、session、物件或擴充等狀態：欄位保存在 worker 可長期存取的位置，而欄位引用的資料卻屬於某一次請求。只要引用在請求堆釋放前未被正確清理，後續請求就可能遇到懸空狀態，形成 use-after-free。 [S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

官方分析將可利用條件分為「生產者」與「消費者」：

| 角色或條件     | 意義                     | 對防護的啟示                     |
| --------- | ---------------------- | -------------------------- |
| 狀態生產者     | 將本請求擁有的狀態放入稍後仍可存取的位置   | 若要檢視異常退出後是否完成對應清理          |
| 狀態殘留      | 沒有清空，或清空後又被晚期操作重新填入    | 僅在較早的 shutdown 階段清空一次可能不夠  |
| worker 復用 | 同一 worker 繼續處理後續請求     | 多 worker 只是調度差異，不是記憶體安全保證  |
| 提前消費者     | 在對應狀態正常初始化前讀取、釋放或判斷殘留值 | 必須檢查初始化之前的 INI、session 等路徑 |

這些條件需要組合成立；任一次錯誤日誌本身並不證明漏洞已經被成功利用。 [S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

#### 它不以 OOM 為必要前提

致命錯誤可能使成對的狀態發布與恢復過程被打斷。例如編譯或解析失敗、未捕獲錯誤、`require` 失敗及執行逾時，都可能參與特定狀態的殘留。清理後期的非致命診斷也可能重新填入已經清空過的錯誤訊息。 [S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

因此，將 `memory_limit` 改為無限制，無法覆蓋這組漏洞。

#### 「初始化之前」需要分別看待

兩類已確認消費者的時序不同：

- **早期 INI 診斷**：某些按請求應用的配置在普通 executor 初始化前發出 warning、notice 或 deprecation，診斷處理可能存取舊錯誤狀態。
- **session upload progress**：請求體解析過程中可能提前處理 session，而常規模組 `RINIT` 尚未完成；不能以應用沒有明確呼叫 `session_start()` 推斷路徑不存在。 [S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

並非所有 INI 配置都具有相同風險時機。 mod\_php 的目錄級配置與 FPM 前端傳入的 `PHP_VALUE` / `PHP_ADMIN_VALUE` ，需要與普通 `php.ini` 、 FPM pool 啟動配置及 FPM `.user.ini` 區分。後幾者的應用時機不同，不能一概稱為同一種早期消費者。 [S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

關閉 `display_errors`、`log_errors`，降低 `error_reporting`，或使用 `@`，只影響診斷的可見性；相關內部狀態可能在決定是否輸出日誌之前已經被存取。 [S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

## 3. 修復版本與補丁選擇

### 3.1 上游正式修復基線

| 目前 PHP 分支 | 首個包含本次正式修復的版本 | 建議                          |
| --------- | ------------- | --------------------------- |
| 8.2       | 8.2.35        | 升級至該版本或包含相同修復的後續版本          |
| 8.3       | 8.3.36        | 同上                          |
| 8.4       | 8.4.27        | 同上                          |
| 8.5       | 8.5.12        | 同上                          |
| 8.1 及更早版本 | 上游常規支援已結束     | 優先遷移至支援分支；短期核對發行版或 LTS 廠商回補 |

版本與支援狀態依據 PHP 官方公告，時間基準為 2026 年 10 月 22 日。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)

這些是**分支內的修復門檻**，不能用一句「所有低於 8.5.12 的版本均未修復」替代。 8.2.35 與 8.4.27 等其他分支版本已經包含修復。

### 3.2 發行版版本號碼不能只看上游部分

發行版常在較舊的上游版本號基礎上回補安全修復。驗收應同時檢查發行版、倉庫來源、完整包版本和安全公告。

例如，Ubuntu USN-8948-1 列出的 Ubuntu 24.04 LTS 修復套件版本為：

```text
8.3.6-0ubuntu0.24.04.13
```

它的上游部分仍是 `8.3.6`，但該發行版完整包版本已列入本次修復公告。這個結論只適用於對應發行版和套件來源，不能推廣到任意同樣顯示 `8.3.6` 的建置。 [S10](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-10)

### 3.3 實際上應選擇哪一種 patch

| 場景               | 優先方案                 | 驗收重點                 |
| ---------------- | -------------------- | -------------------- |
| 使用發行版 PHP 套件     | 安裝廠商發布的安全性更新         | 公告同時涵蓋兩個 CVE；完整包版本正確 |
| 使用官方 PHP 容器或自建鏡像 | 更新基礎運行時，重新建置並部署      | 運行實例使用新鏡像；舊副本全部退出    |
| 自編譯支援分支          | 使用該分支正式安全版本或完整官方補丁集  | 分支匹配、依賴補齊、擴展兼容與回歸通過  |
| 受制於 7.4、8.0、8.1  | 優先廠商回補；必要時評估官方應急源碼分支 | 明確行為變化，並安排遷移至支援版本    |

官方已發布補丁，實際修復應從這些補丁出發。第 6 節中的程式碼片段用於說明設計與審查重點，不構成可單獨套用的完整補丁。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S4](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-4)[S6](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-6)

## 4. 正式修復流程

### 4.1 盤點真正處理請求的運行時

建議形成一張簡短台賬，至少記錄：

- 入口網域名稱或服務、反向代理後端、PHP SAPI。
- PHP 分支、完整軟體包版本或鏡像摘要、建置來源。
- FPM pool、實際服務單元、容器或 Pod、副本數量。
- 已載入擴充功能、主配置與額外設定檔。
- 是否存在其他 PHP 版本、舊部署副本或可直接存取的來源站入口。

這些是實施建議，目的是使「已升級」能對應到每個實際流量入口。特別檢查命令列 PHP 與 Web PHP 使用不同版本、鏡像建置完成但舊容器仍運作、部分 pool 或副本未替換等情況。

### 4.2 選擇並部署正確更新

依第 3 節確認修復版本，優先使用既有可信任包源或受控建構鏈。更新範圍應包含實際承載請求的元件，例如 FPM 套件、Apache PHP 模組、CGI 二進位，或將 PHP 嵌入其中的服務建置。

升級前保留配置與套件清單，在與生產相近的環境先驗證啟動和關鍵業務。對於自行維護的擴展，檢查對應 PHP 版本的建置與運作相容性。只從另一個分支挑取一個看似相關的提交，不能保證整個修復集已完整落地。

### 4.3 重啟或捲動取代運行實例

安裝檔案與進程載入的新程式碼是兩件事。應重啟對應服務，或完成滾動替換，並確認舊 worker 與舊容器已退出。

對於 mod\_php，重啟物件通常是承載模組的 Apache 進程；對於嵌入 PHP 的服務，需要取代承載進程本身。對 FPM 而言，清理 OPcache 不能取代運行時更新與舊 worker 退出。

採用優雅切換時，需要檢查舊代進程是否仍處理長連線或未完成請求。驗收記錄應包含實際服務、部署版本、變更完成時間及舊實例退出結果。

### 4.4 從真實 Web 請求驗證結果

推薦把下面幾項證據組合起來，而不是只依賴單一版本指令：

| 證據             | 能證明什麼             | 不能單獨證明什麼        |
| -------------- | ----------------- | --------------- |
| 套件管理器或鏡像元數據    | 安裝來源與完整建置版本       | 流量已經切換到該實例      |
| 行程及部署狀態        | worker 或容器完成替換    | 對外入口一定路由到它      |
| 經真實入口訪問的受限診斷結果 | 實際 Web SAPI 和運行配置 | 發行版回補是否涵蓋兩支 CVE |
| 廠商公告或完整補丁記錄    | 本次漏洞修復包含在該建置中     | 所有副本均已部署        |

可透過已有內部診斷能力，或臨時且受存取控制的診斷入口，核對 `PHP_VERSION`、`PHP_SAPI`、載入的設定檔及緊急設定。確保請求沒有被 CDN 或頁面快取直接返回；完成後移除臨時診斷入口。

`php -v` 通常只說明目前 shell 選擇的 CLI 二進位；`php-fpm -i` 等指令也不等於對現存、正在接收流量的 worker 做了驗證。不要將完整 `phpinfo()` 頁面長期暴露到公網。

### 4.5 業務回歸與緊急配置退出

圍繞本次變更影響的功能驗證正常登入、session 讀寫、表單與上傳、匯入、錯誤處理和 worker 穩定性。檢查錯誤率、回應延遲、記憶體峰值、進程退出及重建頻率是否異常。

若暫時設定了 `memory_limit=-1`，在正式修補程式生效後恢復與業務容量相符的有限預算；若已設定 `pm.max_requests=1`，在確認修復後恢復經過容量評估的生命週期配置。輸入大小限制和來源存取控制可依業務需要保留。

若升級出現相容性問題，應優先暫停受影響入口、限制其外部存取或調整應用，再處理回退。直接讓未修復運行時重新對公網服務，會重新開啟原有風險。

## 5. 無法立即升級時的緩解措施

本節用於短期降低暴露或改善可用性。每項措施只涵蓋特定路徑，多個措施組合也不等價於完整修復。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

### 5.1 優先控制進入 PHP 的流量

如果業務允許，將敏感服務暫時限制為可信任來源，或在 PHP 之前執行存取控制。需要上傳的業務收緊請求體、欄位、part、part 內頭部數量及嵌套深度；不需要 multipart 的業務可臨時在前端拒絕這類要求。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

這些限制要涵蓋所有通往 PHP 的入口。僅攔截名為「上傳」的 URL，會漏掉其他仍由 PHP 自動解析請求體的入口。對於分塊傳輸、缺少可用聲明長度等情況，應以實際讀取量執行限制；應用再次解壓縮或展開內容時，還要有自己的輸出大小預算。

### 5.2 FPM pool 設定模板

以下內容放在**實際生效的 FPM pool 配置段**中，不能原樣放入 `php.ini`。這裡的 8M 和 4M 是演示值，應根據業務調整；限制整個 POST 請求時也要為表單欄位與 multipart 邊界保留空間。 [S11](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-11)[S12](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-12)

```ini
; Temporary mitigation: evaluate capacity before applying.
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 4M
php_admin_flag[session.upload_progress.enabled] = off
```

**僅 PHP 8.5**，另加：

```ini
php_admin_flag[fatal_error_backtraces] = off
```

各項作用與邊界如下：

| 配置                                    | 預期作用                   | 必須保留的限制說明                         |
| ------------------------------------- | ---------------------- | --------------------------------- |
| `memory_limit=-1`                     | 去掉可預測的 PHP 請求記憶體上限觸發條件 | 不防底層分配失敗；取消了原有預算，可能增加記憶體耗盡和服務中斷風險 |
| 較小的 `post_max_size`                   | 縮小進入解析流程的資料規模          | 未修復解析器有已知缺口；無法單獨阻止記憶體放大           |
| `upload_max_filesize < post_max_size` | 限制單一檔案大小並保留請求開銷空間      | 不約束全部欄位、元資料或應用程式內分配               |
| 關閉 upload progress                    | 阻斷已確認的 session 相關路徑    | 不覆蓋其他全域狀態變體                       |
| PHP 8.5 關閉 fatal backtrace            | 阻斷已確認的相關狀態生產者          | 不覆蓋 session 等其他路徑                 |

措施邊界來自官方公告；pool 語法與管理層級配置語意請參閱 PHP 手冊。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)[S11](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-11)

管理級 `php_admin_*` 設定不能由應用程式透過 `ini_set()` 改寫。仍應審查所有 pool、目錄級與前端傳入配置，確認實際請求上的值符合預期。修改後重建全部 worker，避免已有行程繼續持有舊狀態。

如果選擇直接修改 `php.ini`，語法應改為：

```ini
memory_limit = -1
post_max_size = 8M
upload_max_filesize = 4M
session.upload_progress.enabled = Off
```

與 pool 中的 `php_admin_value` 不同，僅在 `php.ini` 設定 `memory_limit=-1` 無法阻止應用程式再次修改它。應檢查框架、應用程式碼及其他配置是否重新設定有限值；需要強制執行時，使用適合當前 SAPI 的管理層級設置，並核對實際生效值。 [S11](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-11)[S12](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-12)

PHP 8.5 才追加 `fatal_error_backtraces = Off`。不要在應用程式碼中使用 `ini_set()` 作為關閉 upload progress 的補救，也不要依賴 FPM `.user.ini` 來保證它在請求解析前生效。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)

### 5.3 取消 PHP 記憶體上限時如何控制代價

`memory_limit=-1` 是未修復環境的臨時路徑緩解，不應作為長期預設配置照搬。當應用或請求失控時，它可能耗盡更多宿主機記憶體。因此，使用前應評估並發數、單 worker 峰值及服務總容量，同時部署前端輸入限制。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

容器或 cgroup 記憶體限制可以提供可用性邊界，但不能保證分配永不失敗；限制觸發時，也可能終止整個容器、master 和全部 worker。隔離粒度及終止策略需要結合部署評估，不能稱為這兩個 CVE 的完整防護。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

不要以 `RLIMIT_AS`、`RLIMIT_DATA` 或對應的進程位址空間限制取代上述策略；它們可能直接造成底層分配失敗，進入仍然有問題的 OOM 路徑。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)

### 5.4 Nginx 設定範例

適用於 Nginx 向 PHP-FPM 轉送請求的部署。可在實際承載服務的配置層級設定：

```nginx
client_max_body_size 8m;
fastcgi_request_buffering on;
```

`client_max_body_size` 限制請求體大小；`fastcgi_request_buffering on` 讓 Nginx 先讀取完整請求體，再傳送至 FastCGI 後端。是否在某個 `server` 或 `location` 中生效，需要結合已有繼承和覆蓋關係檢查。 [S13](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-13)[S14](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-14)

**僅在業務完全不需要 multipart 時**，可在對應服務入口追加拒絕規則：

```nginx
if ($http_content_type ~* "multipart/form-data") {
    return 403;
}
```

這是使用 `if` 和 `return` 的簡單入口限制模板，而不是解析器漏洞的通用過濾規則。部署前先驗證設定語法與正常要求，並檢查自訂 `error_page` 是否把 403 請求重新交給 PHP。字串匹配對所有解析差異不提供完整保證。 [S15](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-15)

此外，這些配置不會自動限制應用自行解壓縮後的資料量、欄位數量或 PHP 物件數；需要上傳的業務應使用能夠理解其請求結構的額外限制。

### 5.5 可選措施：FPM 每個 worker 只處理一次請求

對能承受開銷的 FPM 部署，可評估短期設定：

```ini
pm.max_requests = 1
```

並重建已有 worker。它在 worker 復用層面阻斷已描述的跨請求鏈，但會增加進程創建和初始化開銷；同時不能修復 CVE-2026-109618 的同請求 OOM 與清理問題。值較小但大於 1 時，仍存在請求復用視窗。 [S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)[S11](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-11)

### 5.6 WAF 與 Cloudflare 的適用邊界

Cloudflare 已公佈針對 PHP2Shell 的防護，包括 Free 計畫在內的部署安排。使用其服務時，應核對實際流量是否經過代理、防護規則是否生效，以及源站能否被直接繞過；付費計劃還需檢查相應 Managed Rules 的配置與例外。 [S16](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-16)

該廠商說明的部分偵測利用回應訊號，因此不能將所有防護理解成「每次攻擊都在到達 PHP 之前被攔截」。 WAF 可輔助減少暴露並提供觀察信息，但繼續升級 PHP 仍是必要工作。 [S16](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-16)

### 5.7 常見措施為何不足

| 措施或判斷                                    | 不足之處                                         |
| ---------------------------------------- | -------------------------------------------- |
| 只關閉 `file_uploads`                       | 不能覆蓋全部 multipart 處理和應用自身的 OOM 路徑             |
| 設定 `enable_post_data_reading=Off`        | 改變自動填充 POST/FILES 的行為；請求體仍可由應用程式讀取，也可能破壞正常業務 |
| 關閉錯誤顯示、日誌或使用 `@`                         | 內部診斷處理仍可能存取懸空狀態                              |
| 增加 worker 數量                             | 不建立安全的狀態清理機制，也不消除單 worker 復用                 |
| 僅配置 `disable_functions` 或 `open_basedir` | 這些限制不能修復 C 引擎層記憶體破壞                          |
| 只檢查一次版本或單一副本                             | 無法證明所有入口與運行實例都已替換                            |
| 沒有看到異常日誌                                 | 不能證明漏洞不存在，也不能證明先前未被利用                        |

其中 PHP 配置與漏洞機制依據見 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S3](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-3)[S12](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-12)；關於覆蓋、驗收和權限邊界的判斷是基於這些機制提出的實施建議。

## 6. 官方 patch 的實現思路與審閱重點

### 6.1 應使用完整、匹配分支的修復

PHP 8.5 的代表性官方投稿為：

```text
31c0ea7d7ff1d1fccb6492e52dab544011628065
Avoid state corruption via bailout
```

提交明確關聯兩個 CVE，既調整 OOM 退出機制，也修復可能在初始化階段存取的全域狀態。提交頁面與完整 diff 請參閱 [S4](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-4)[S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)。其他分支應使用自己的正式安全發布或匹配補丁，不能假設 8.5 的改動可直接應用到任意舊版本。

### 6.2 OOM 修復：先恢復可處理狀態，再終止請求

正式實作引入了軟、硬兩個層次的 OOM 處理：達到軟限制時記錄待處理狀態，並在 VM 等安全位置進行受控退出；可失敗分配介面則允許呼叫方明確處理失敗。對於無法直接返回失敗的分配，若預期超過更高的硬性閾值，便直接終止進程，避免在不安全的中間狀態繼續處理請求。 [S2](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-2)[S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

以下是 8.5 diff 中用於標記待處理 OOM 的關鍵程式碼節選：

```c
EG(delayed_oom).state = ZEND_OOM_STATE_PENDING;
zend_atomic_bool_store_ex(&EG(vm_interrupt), true);
```

VM 中斷處理及其他安全位置隨後呼叫 `zend_handle_delayed_oom()`。其使用者程式碼執行上下文使用受控的 unwind 路徑；硬 OOM 路徑呼叫 `_exit(137)`。 [S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

從設計來看，重要變化是：**避免在結構正處於中間狀態時隨意跨越 C 呼叫棧，把退出放在能夠維護狀態約束的位置**。軟限制觸發後可能需要額外記憶體完成此過程，因此不能把新的軟閾值理解為進程總記憶體的絕對上限。

也不能概括成「PHP 已刪除所有 `zend_bailout()`」。補丁仍在特定上下文使用相關機制；修復的是危險的退出時機及與之配套的狀態管理。 [S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

### 6.3 分配呼叫者與 multipart 解析必須一起修改

如果只把一個分配函數改成“失敗返回 NULL”，而原來的呼叫者仍假定永遠返回有效指針，就會引入新的空指針訪問或未完成清理。補丁中的可失敗分配接口，需要與呼叫方檢查及異常傳播共同審閱。 [S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

multipart 相關修復還包括以實際讀取量執行累積檢查、減少無用或重複頭部的處理，並在 OOM 待處理狀態下採用一致的退出與清理邏輯。這些改動既縮小資源放大面，也使解析器遵守新的 OOM 協定。 [S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

對維護自有分支的團隊，建議以下問題作為程式碼審查重點：

- 狀態在完全初始化前是否已對外可見？
- 分配失敗或回呼異常後，所有權是否仍然唯一且明確？
- 中途失敗能否到達統一清理出口？
- 清理函數能否辨識未初始化或已釋放欄位？
- 解析預算是否以實際處理量為依據，而不僅信任請求宣告？
- 新的失敗回傳值是否已被所有呼叫者處理？

這些都是依據修復機制歸納的審閱問題，並非對某個未提供程式碼庫已經完成的稽核結論。

### 6.4 跨請求修復：初始化更早，最終清理更晚

對應 CVE-2026-109619，補丁同時調整多個生命週期邊界。以下列出的文件和操作以 PHP 8.5 官方 diff 為例。 [S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

| 位置                          | 改動方向                                     | 解決的問題                |
| --------------------------- | ---------------------------------------- | -------------------- |
| `Zend/zend_execute_API.c` 等 | 重設錯誤、異常、handler、物件等執行器狀態                 | 請求結束後仍存在可被下一請求存取的舊引用 |
| `main/main.c` 的啟動路徑         | 在 SAPI 啟動前呼叫 `php_basic_early_rinit()`   | 提前消費者發生時，相關基礎狀態尚未初始化 |
| `main/main.c` 的關閉路徑         | 銷毀 HTTP globals 後標記為未定義                  | 釋放後的值仍被當成有效對象        |
| 請求堆最終釋放之前                   | 再次清理最後錯誤訊息                               | 較晚的清理診斷重新填入錯誤狀態      |
| `ext/session/session.c`     | upload progress 早期路徑先初始化 session globals | 常規模組 RINIT 之前訪問舊狀態   |
| 序列化相關程式碼                    | 早期處理中限制類別解析與使用者回調                        | 初始化未完成時執行額外使用者程式碼    |

例如，啟動順序中加入了：

```c
zend_activate();
php_basic_early_rinit();
sapi_activate();
```

HTTP globals 銷毀後補上狀態破壞標記：

```c
zval_ptr_dtor(&PG(http_globals)[i]);
ZVAL_UNDEF(&PG(http_globals)[i]);
```

這些節選表達了兩個通用原則：**第一次可能使用某類狀態之前就要初始化；最後一次可能重新產生該狀態之後才進行最終清理。** 只在常規 RINIT 或較早的 shutdown 中修一次指針，可能遺漏更早或更晚的訪問。 [S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

### 6.5 為什麼不建議自製“一行修復”

把所有 `zend_bailout()` 替換成 `_exit()`，或僅在某個入口加一個空指標檢查，都會跨越大量不同的執行上下文。它們可能遺漏其他狀態字段，也可能改變析構、擴展回調、進程宿主和請求結束語義。

對於受支援版本，優先採用已經發布的完整修復。自有分支的移植應記錄修補程式來源、適用基準、衝突處理和行為變化，並使用對應上游迴歸案例及本業務流程驗證。這裡的建議來自對補丁跨 allocator、VM、session 與請求生命週期改動範圍的分析。 [S4](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-4)[S5](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-5)

## 7. PHP 7.4、8.0、8.1 的緊急回補

PHP 官方針對嚴重性提供了三個舊分支的最小原始碼回補，分支名分別為：

```text
PHP-7.4-CVE-2026-109618-109619
PHP-8.0-CVE-2026-109618-109619
PHP-8.1-CVE-2026-109618-109619
```

分支連結見 [S7](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-7)[S8](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-8)[S9](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-9)。這些是針對本次漏洞的緊急交付，不表示上游恢復對舊分支的常規支持，也不取代其他安全更新。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)

### 7.1 以 PHP 8.1 回補為例

PHP 8.1 的相關提交是：

```text
1d7dec178a094e6e75b229ce22754045f8c6070a
```

其策略更偏向快速失敗：在對應 OOM 路徑中輸出診斷後呼叫 `_exit(1)`，並包含全域狀態及其他相關修正；同時在內部停用 session upload progress 的相應處理。相關原始碼提交請見 [S6](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-6)。

這與受支援分支中較完整的延遲 OOM 設計存在行為差異。不能只因為配置裡仍顯示 upload progress 開啟，就認為經過該回補的內部處理行為也保持不變。

### 7.2 部署時需要接受的代價

直接退出程序可能會使目前請求失敗，跳過正常 PHP shutdown 回調及部分應用收尾；若宿主採用執行緒模型，還需評估整個宿主程序退出對其他並發工作造成的影響。進程管理器是否能及時拉起替代進程，也應納入驗證。

因此，舊版本用戶應按順序考慮：

1. 遷移至受支援 PHP 分支及其修復版本。
2. 使用明確覆蓋兩款 CVE 的發行版或 LTS 廠商更新。
3. 確實受制於舊版原始碼時，採用符合版本的官方應急回補，驗證完整改動與相容性，並安排後續遷移。

這裡的「最小回補」描述的是官方選擇的兼容性與實現範圍，不應自動解釋為「已知不完整的漏洞修復」。應依對應分支源碼及廠商公告判斷，不自行刪減其中的配套改動。 [S1](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-1)[S6](https://keendigit.com/zh-hant/insights/php2shell-remediation-guide#source-6)

## 8. 驗收標準與後續檢查

建議以下結果作為本次修復完成的依據：

| 驗收項    | 完成標準                                          |
| ------ | --------------------------------------------- |
| 漏洞覆蓋   | 建置或廠商公告明確修復 CVE-2026-109618 和 CVE-2026-109619 |
| 部署覆蓋   | 全部入口、pool、服務及副本使用修復後的運行時                      |
| 行程生效   | 舊 worker、舊宿主程序和舊容器全部退出                        |
| 真實請求驗證 | 經實際 Web 連結確認 SAPI、建置與配置，排除快取誤導                |
| 業務可用性  | session、上傳、匯入、錯誤處理等關鍵功能透過正常回歸                 |
| 臨時措施收尾 | 無限記憶體及極端 worker 回收配置已按容量計畫恢復或有明確保留原因          |
| 變更證據   | 記錄包版本或鏡像摘要、更新範圍、完成時間與驗證結果                     |

上述為實施建議。若需驗證 OOM 行為、異常退出或自訂補丁，應在隔離環境中使用上游迴歸測試或受控故障注入，避免以生產環境反覆製造記憶體耗盡作為驗收方式。

同時檢查更新前後的 PHP fatal、worker 崩潰、異常重啟、請求錯誤率及 WAF 事件。日誌只能提供調查線索：出現 OOM 不等於已經被利用，缺少警告也不能證明未發生過利用。升級修復的是未來可達到的漏洞路徑；如已發現文件竄改或憑證外洩等異常，應另行進行事件調查。

## 附錄：引用來源與鏈接

所有連結均集中在本附錄。漏洞公告、修補程式和廠商通告以 **2026 年 10 月 22 日** 的核驗結果為基準；後續部署應繼續查看供應商更新。正文 \[Sx] 對應以下編號。

### S1 — PHP 官方安全公告與修復版本

- 資料來源：PHP 項目，2026 年 10 月 21 日。
- 用途：風險範圍、四個正式修復版本、官方臨時措施及舊分支應急回補說明。
- 參考連結: [PHP 2026 年公告歸檔中的本安全公告](https://www.php.net/archive/2026.php#2026-10-21-5)

### S2 — CVE-2026-109618 官方技術公告

- 資料來源：php/php-src GitHub Security Advisory，2026 年 10 月 21 日。
- 標識：GHSA-w8hw-w9fx-j79w。
- 用途：OOM、multipart 放大、SAPI 差異與緩解措施的覆蓋邊界。
- 參考連結: [RCE via OOM corruption](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w)

### S3 — CVE-2026-109619 官方技術公告

- 資料來源：php/php-src GitHub Security Advisory，2026 年 10 月 21 日。
- 標識：GHSA-6wmf-4rv5-p3rp。
- 用途：跨請求懸空狀態、生產者與消費者、提前初始化、配置緩解。
- 參考連結: [RCE via stale global state](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

### S4 — PHP 8.5 官方修復提交

- 來源：php/php-src。
- 提交：`31c0ea7d7ff1d1fccb6492e52dab544011628065`。
- 用途：確認正式提交同時修復兩個漏洞，並說明整體改動方向。
- 參考連結: [Avoid state corruption via bailout](https://github.com/php/php-src/commit/31c0ea7d7ff1d1fccb6492e52dab544011628065)

### S5 — PHP 8.5 官方修復完整 diff

- 來源：同一官方提交的 diff。
- 用途：核對 allocator、VM、HTTP globals、session、序列化和請求生命週期的具體實現。
- 參考連結: [官方完整 diff](https://github.com/php/php-src/commit/31c0ea7d7ff1d1fccb6492e52dab544011628065.diff)

### S6 — PHP 8.1 官方緊急回補提交

- 來源：php/php-src。
- 提交：`1d7dec178a094e6e75b229ce22754045f8c6070a`。
- 用途：核對舊分支快速退出及 upload progress 行為變化。
- 參考連結: [PHP 8.1 緊急回補提交](https://github.com/php/php-src/commit/1d7dec178a094e6e75b229ce22754045f8c6070a)
- 參考連結: [對應完整 diff](https://github.com/php/php-src/commit/1d7dec178a094e6e75b229ce22754045f8c6070a.diff)

### S7 — PHP 7.4 官方緊急回補分支

- 資料來源：php/php-src，PHP 官方安全公告所列原始碼分支。
- 參考連結: [PHP-7.4-CVE-2026-109618-109619](https://github.com/php/php-src/tree/PHP-7.4-CVE-2026-109618-109619)

### S8 — PHP 8.0 官方緊急回補分支

- 資料來源：php/php-src，PHP 官方安全公告所列原始碼分支。
- 參考連結: [PHP-8.0-CVE-2026-109618-109619](https://github.com/php/php-src/tree/PHP-8.0-CVE-2026-109618-109619)

### S9 — PHP 8.1 官方緊急回補分支

- 資料來源：php/php-src，PHP 官方安全公告所列原始碼分支。
- 參考連結: [PHP-8.1-CVE-2026-109618-109619](https://github.com/php/php-src/tree/PHP-8.1-CVE-2026-109618-109619)

### S10 — Ubuntu 安全公告 USN-8948-1

- 資料來源：Canonical / Ubuntu，2026 年 10 月 21 日。
- 用途：發行版回補及完整軟體包版本範例。
- 參考連結: [USN-8948-1: PHP vulnerabilities](https://ubuntu.com/security/notices/USN-8948-1)

### S11 — PHP-FPM 設定手冊

- 資料來源：PHP 官方文件。
- 用途：`php_admin_value`、`php_admin_flag`、`pm.max_requests` 等設定語意。
- 參考連結: [PHP-FPM Configuration](https://www.php.net/manual/en/install.fpm.configuration.php)

### S12 — PHP 核心 INI 設定手冊

- 資料來源：PHP 官方文件。
- 用途：請求體、上傳、記憶體與自動 POST 讀取組態的定義及適用範圍。
- 參考連結: [Description of core php.ini directives](https://www.php.net/manual/en/ini.core.php)

### S13 — Nginx 請求體大小限制

- 資料來源：Nginx 官方文件。
- 用途：`client_max_body_size` 的意義及可用配置層級。
- 參考連結: [ngx\_http\_core\_module / client\_max\_body\_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size)

### S14 — Nginx FastCGI 請求緩衝

- 資料來源：Nginx 官方文件。
- 用途：`fastcgi_request_buffering` 的處理順序與作用。
- 參考連結: [ngx\_http\_fastcgi\_module / fastcgi\_request\_buffering](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_request_buffering)

### S15 — Nginx 條件與返回指令

- 資料來源：Nginx 官方文件。
- 用途：`if` 與 `return` 的設定語法。
- 參考連結: [ngx\_http\_rewrite\_module](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if)

### S16 — Cloudflare PHP2Shell 防護說明

- 資料來源：Cloudflare 官方部落格。
- 用途：其 WAF 部署範圍、Free 計畫安排及偵測機制說明。
- 參考連結: [Cloudflare deploys protections against php2shell vulnerability](https://blog.cloudflare.com/php-vulnerabilities-waf-protection/)

## 安全維護咨詢

需要協助更新 PHP 系統？我們可以評估影響範圍、制定更新計劃，並驗證實際運行的應用。

[咨詢安全更新](<https://keendigit.com/zh-hant/contact?service=security-remediation#form>)

[原始頁面](<https://keendigit.com/zh-hant/insights/php2shell-remediation-guide>) · [內容索引](<https://keendigit.com/zh-hant/llms.txt>)

KeenDigit LLC · 懷俄明州登記編號: 2026-002106155

[前往懷俄明州州務卿官網核驗](<https://wyobiz.wyo.gov/Business/filingSearch.aspx>)

© 2026 KeenDigit LLC · 美國懷俄明州 Sheridan · 保留所有權利。
