← 返回列表

PHP2Shell 炸了:CVSS 9.2,公開前一天就有人在打,而這兩個洞在代碼裏躺了十年

itadol5j

先說結論:PHP 出了一個 CVSS 9.2 的未授權遠程代碼執行,編號 CVE-2026-109618 和 CVE-2026-109619,人送外號 PHP2Shell。10 月 20 日公開,10 月 21 日 14:00 UTC 出補丁,而亞馬遜的蜜罐在 10 月 17 日——公開前四天——就記錄到了利用嘗試。

比這更難看的是另一件事:這兩個洞最早能追到 PHP 5.4,也就是說它們至少在代碼裏躺了十年以上。而且 2024 年就有 PHP 核心開發者審計時發現了 OOM 那條路徑,團隊開會討論怎麼修,沒達成一致,然後就沒修。理由是當時沒人認爲能真的寫出利用。

這句話現在看起來特別諷刺。寫不出來的原因不是洞不重要,是這條鏈太複雜,複雜到超出人類研究者的實際能力邊界。然後 AI 來了,把它寫出來了。

PHP2Shell 漏洞封面:影響範圍與暴露主機

一、先把「多國緊急響應」這句話拆開看

標題黨最愛的說法是「全球拉響警報」。這次還真不是誇張,但警報的成色得分清楚。

  • PHP 官方:10 月 20 日先發預告,說 21 日 14:00 UTC 出安全版本,如果細節提前泄露或出現野外利用就提前發。結果 CVE 編號當天就被人捅到 Hacker News,原定 10 月 22 日的發佈被迫提前一天。
  • CERT-EU:發佈 advisory 2026-018,把兩個 CVE 都列進去了。
  • Cloudflare:CTO Dane Knecht 10 月 21 日直接說「已在看到早期攻擊浮現」,WAF 規則全量下發,包括免費用戶。但他自己強調這只是 stopgap,真正的解法是打補丁。
  • 亞馬遜威脅情報:MadPot 蜜罐 10 月 17 日就抓到嘗試,21 日又抓到一批,payload 和基礎設施指向多個不同的攻擊方。原話是 php2shell「已經在被廣泛利用」。
  • watchTowr:兩個洞都復現了,同時觀察到針對兩者的利用嘗試。

所以「已發現攻擊」不是渲染,是事實。而「多國緊急響應」也不算吹——只是這個響應的主體是廠商、CDN 和應急組織,不是哪個國家的政府在開發佈會。

二、兩個洞,兩種完全不同的死法

很多人以爲是一個洞兩個編號,不是。這是兩條獨立的攻擊路徑,各自 CVSS 9.2。

兩個漏洞的技術路徑對比

CVE-2026-109618:內存耗盡的時候炸

PHP 在內存分配失敗時會中斷請求處理。問題出在:這個時候內部的請求數據可能只初始化了一半,而隨後的清理邏輯會把這塊沒初始化完的爛數據當成有效數據來用。

觸發方式很樸素:構造 multipart 請求,把內存撐爆。詭異的地方在於,請求體積看起來完全可以符合你配置的上限——它撐爆的不是你設的 post_max_size,而是解碼和內部處理環節的消耗。

最狠的是 mod_php。Apache 的 mod_php 在請求啓動失敗時仍然會執行清理,所以這條鏈能在任何應用代碼運行之前完成。你 PHP 代碼寫得再幹淨、再沒有漏洞,也攔不住。

PHP-FPM 在啓動失敗時會直接殺掉 worker,恰好切斷這條鏈,所以官方說 mod_php 風險最高。但注意——這不代表 FPM 就安全,官方明確說 FPM 在成功啓動之後仍有被利用的可能。

CVE-2026-109619:請求之間的髒狀態

這個更陰。PHP 會複用 worker 進程處理多個請求。上一個請求釋放掉的內存,指針還留在內部狀態裏;下一個請求進來,在正常初始化把它清掉之前,先把這塊懸空地址讀了。

致命錯誤(內存耗盡、執行超時)會打斷狀態清理。更騷的是,shutdown 期間的某些非致命診斷,還會把已經重置的錯誤狀態重新寫回去。

官方確認的路徑包括:PHP 8.5 上啓用 fatal_error_backtraces(默認開)時通過致命錯誤回溯的 RCE,以及 mod_php 和 FPM 上的 session 生命週期 RCE。session.upload_progress 默認開啓,可以充當髒狀態的早期消費者——而且這一步根本不需要應用調用 session_start()。

這個洞還附帶內存泄露。泄露的是什麼?是進程內存裏其他請求的密碼、token、API key、證書。Wiz 直接拿 Heartbleed 來類比,這個比喻不算過分。

三、時間線,比標題更值得看

PHP2Shell 事件時間線:從 2024 年擱置到 10-17 野外利用
時間發生了什麼
2024 年PHP 核心開發者審計時發現 OOM 那個 bug,團隊對修法沒共識,擱置
2026-08Calif 的 Ryan Austin 用 OpenAI GPT-5.6 Sol 找出漏洞;Wiz 獨立發現
2026-10-17亞馬遜 MadPot 蜜罐記錄到利用嘗試,比公開早四天
2026-10-20CVE 編號在 Hacker News 和社交媒體泄露,PHP 發預告
2026-10-2114:00 UTC 發佈 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35

10 月 17 日這個日子必須單獨標出來。公開日是 20 號,但攻擊 17 號就發生了。亞馬遜的建議很直接:排查起點不要設在披露日,往前推到至少 10 月 17 日。

至於攻擊者怎麼提前拿到信息的,亞馬遜說「不清楚」。這事兒沒法深究,但你得接受一個現實——「披露日」從來不是攻擊開始的那天,只是你終於知道的那天。

四、這次真的是 AI 挖出來的

Wiz 的博客裏有句話我讀了兩遍:「這些底層缺陷已經存在了幾十年,但要證明它們可被利用,需要一條異常複雜的步驟鏈,處於人類研究者實際能力邊緣。前沿 AI 模型大幅降低了這個門檻。」

具體點:Calif 的研究員 Ryan Austin 是在 OpenAI 的「Patch the Planet」項目裏,用 GPT-5.6 Sol 找到的。Wiz 獨立發現了同一批問題。爲了打通利用,得把多個缺陷串成一條鏈,還要針對每個目標的內存佈局反覆調試適配——Wiz 說前沿模型讓他們在幾小時內就能爲不同應用開發出可用利用。

這件事的意義不在「AI 又贏了一次」。意義在於「複雜性」這道護城河正在失效。

過去二十年,很多老漏洞之所以沒被打,不是因爲它們不嚴重,是因爲利用門檻太高——需要頂級研究者投入幾周,還需要一點運氣。所以大家心照不宣地把它們歸到「理論上有風險」那一欄。現在這個護欄沒了。

那些躺在你係統裏、被評估爲「利用難度高、暫不處理」的十年老洞,評級得重做了。

五、你該升到哪一版

PHP 各分支修復版本對照表
分支受影響版本處置
PHP 8.5< 8.5.12升到 8.5.12
PHP 8.4< 8.4.27升到 8.4.27
PHP 8.3< 8.3.36升到 8.3.36
PHP 8.2< 8.2.35升到 8.2.35
PHP 7.4 / 8.0 / 8.1全部官方無版本發佈,只有源碼級 backport
PHP 5.4 – 7.3全部EOL,官方不給修,只能自己升或找廠商

幾個實操提醒:

  • Linux 發行版和 LTS 廠商提前拿到了補丁,用發行版包的去查你們廠商的 advisory,別急着源碼編譯。
  • 用 rpms.remirepo.net 的注意:PHP 官方明確說了那個源在 10 月 21 日不會有更新,讓你換成發行版包或者自己從源碼編。
  • PHP 8.5 的 Windows 二進制也在官方下載頁,別說「Windows 沒法升」。
  • 別以爲跑在容器裏就沒事——容器鏡像裏的 PHP 版本該查還得查。

六、上不了補丁,就先做這四件

先聲明:下面這些沒有一條能讓你變安全。PHP 官方的原話是「減少對特定攻擊路徑的暴露,但不使安裝變安全」。它們的價值是給你爭取打補丁的時間。

四條臨時緩解措施及其限制

1. 把 memory_limit 設成 -1

目的:幹掉那個可預測的「PHP 內存上限失敗」,也就是 CVE-2026-109618 已確認利用所依賴的觸發條件。

關鍵在怎麼設:要在應用改不動的地方設,比如 FPM pool 的 php_admin_value 或 Apache 配置。設完必須檢查沒有任何 pool、目錄、應用設置把有限值又加回來。然後重啓每一個 worker。

代價說清楚:你去掉的是 PHP 自己的內存護欄,底層分配失敗仍然可能走到那條危險路徑。所以還得配容器或 cgroup 限制兜底——但只能用「只殺受影響 worker」的策略,千萬別用 RLIMIT_AS 或 RLIMIT_DATA,那兩個恰恰會製造出漏洞需要的那種分配失敗。

2. 把 post_max_size 壓小

不傳文件的站點設 8M,要傳文件的設 32M,並保證 upload_max_filesize 比它小。同時在 Web 服務器或代理層加限制——解碼後的請求體積、字段數量、multipart part 數量、header 數量、嵌套深度。這些限制必須覆蓋那些沒有有效 Content-Length 的請求,否則構造一下就繞過去了。

3. 關掉 session.upload_progress

session.upload_progress.enabled = 0

寫在 php.ini、FPM pool 或服務器配置裏,必須早於請求解析生效。用 ini_set() 或者 FPM 的 .user.ini 都太晚了——那時候狀態已經髒了。改完同樣要重啓所有 worker。

4. PHP 8.5 單獨再關一個

fatal_error_backtraces = 0

這條只堵住已確認的致命錯誤回溯路徑,其他變體不管。同樣要求管理員級別設置 + 重啓 worker。

另外官方還提了一條很多人會忽略的:修掉那些攻擊者能觸發的致命錯誤和執行超時,包括回調、上傳、導入處理、清理階段的失敗。還有,把逐請求施加的過時或非法配置項刪掉——它們會在初始化之前吐診斷信息,正好餵給漏洞。

最後這句最容易被誤解:用 error_reporting、display_errors 或者 @ 把診斷藏起來沒用。藏的是顯示,不是發生。

七、這件事真正的教訓

我不想寫成「趕緊打補丁」就完事。補丁當然要打,今天就打。但有些判斷得改。

  1. 「利用難度高」不再等於「可以先放着」。PHP 這個洞的利用鏈複雜到需要 AI 幫忙,而 AI 已經幫上了。你資產清單裏那些標着「理論風險」的老洞,評級標準該重新過一遍。
  2. 語言運行時是單點。WordPress、Drupal、Joomla、Magento、MediaWiki 全跑在 PHP 上,你的應用代碼審計做得再幹淨,PHP 核心出問題照樣一鍋端。基礎設施層的補丁節奏,得和應用層分開管。
  3. 「應用代碼沒跑就被打穿」這種場景,WAF 只能拖延。Cloudflare 自己都說了是 stopgap。把 WAF 當解決方案的,等於把命交給規則覆蓋率。
  4. 國內用 PHP 的老站點非常多。那些跑着 PHP 5.6 / 7.0、早就沒人維護、掛在某個雲主機上的站,就在 1.3 到 190 萬這個暴露面裏。它們不會收到任何通知。

數據口徑留個記錄:W3Techs 說 PHP 佔已知服務端語言的 69.3%,Wiz 說 70%;暴露主機數,安全研究者 Silas Cutler 的粗估是 130 萬臺以上,Henk Poley 的 Shodan 搜索是 190 萬臺以上。這些數字口徑不同,別當精確值用,但量級是一致的——百萬級,全球範圍。

還有一個細節值得記一下:CVE 編號泄露時,跟着流出的 CVSS 分數寫的是 10.0,PHP 官方後來確認那個分數是錯的,實際是 9.2。這種細節沒人會專門闢謠,但它在傳播裏會一直存在。看到 10.0 的說法,你就知道來源是哪一波。

一個躺了十年的洞,兩個月的 AI 輔助研究,四天的提前利用,一天的補丁窗口。這個時間尺度,就是接下來所有基礎軟件的常態。

現在就去查版本。php -v,或者看你容器鏡像的 tag。別等明天。