Tomcat WebSocket deflate 訊息走私
oss-security mailing list (Openwall) · 2026-09-23
漏洞機制
per-message-deflate 是 RFC 7692 定義的 WebSocket 延伸,讓每一則訊息在傳輸前先以 DEFLATE 壓縮,接收端再依框架(frame)標頭中的長度欄位還原。Apache 官方公告的原文只有一句話:Tomcat 對「長度參數」的處理不一致,導致啟用 per-message-deflate 時可能發生WebSocket 訊息走私(message smuggling)。公告本身沒有進一步描述框架層級的還原細節,屬於相對精簡的資安通報,也沒有附上任何重現步驟或概念性驗證程式碼。
從協定設計反推,問題點很可能出在「壓縮前宣告長度」與「解壓縮後實際長度」兩套帳本沒有互相核對。如果 Tomcat 切分訊息邊界時混用了這兩種長度來源,攻擊者精心構造的壓縮酬載就能讓解壓縮後的內容跨過原本應該獨立的訊息邊界,被下游邏輯誤判成另一則訊息的一部分。此類邊界混淆與 HTTP 走私的成因同源,只是戰場換到 WebSocket 的訊息層而非 HTTP 的請求層。官方僅將其列為低風險(low severity),官方公告未提供 CVSS。
用戶端 Frame(RSV1=1,宣告 per-message-deflate)
compressed length = N bytes ← 邊界核對用這個
decompress(N bytes) = M bytes ← 訊息分派卻可能用這個(M != N)
若兩處長度來源沒有互相校驗:
一則攻擊者控制的訊息,解壓縮後的尾端
可能被誤判成「下一則」獨立 WebSocket 訊息的開頭
受影響版本
CVE 編號為 CVE-2026-87022,Apache 官方安全頁與 oss-security 公告交叉確認之後,受影響範圍涵蓋目前仍在維護的三條主線。只要啟用了 WebSocket 且客戶端能協商 per-message-deflate,就落在受影響範圍內,與是否搭配反向代理無關。由於 per-message-deflate 在多數瀏覽器與 WebSocket 用戶端函式庫中預設會嘗試協商,實務上關閉這個延伸的部署反而是少數。
- Apache Tomcat 11.x:
11.0.0-M1至11.0.25(已修補於11.0.26) - Apache Tomcat 10.x:
10.1.0-M1至10.1.59(已修補於10.1.60) - Apache Tomcat 9.x:
9.0.0.M1至9.0.121(同一封 oss-security 公告一併列為受影響,含已停止維護的8.5.x與7.x分支)
受影響的不只是直接面對使用者的應用程式,任何在 Tomcat 前面轉發 WebSocket 流量、並信任其訊息邊界的閘道或訊息代理,都可能因為邊界被混淆而誤判訊息內容。對這類中介系統而言,衝擊可能比終端應用程式本身更大,因為它們通常不會重新做語意層級的驗證,只要 Tomcat 回報的訊息邊界看似合法就會照單全收。
修補與緩解
Apache 已在 11.0.26 與 10.1.60 中修正長度參數的核對邏輯(對應 commit 4fef25fe 與 567a8551),做法是讓訊息邊界判斷統一採用同一套長度來源。升級是官方認可的修補方式,oss-security 公告同時把 9.0.x、以及已停止維護的 8.5.x、7.x 分支也列入受影響版本一併說明。
這顆漏洞並非當天唯一一顆:同一批公告還包含被列為 Important 等級的 CVE-2026-86350(HTTP/2 請求標頭混用的迴歸問題),以及 Moderate 等級的 CVE-2026-86248(OCSP 在 FFM 實作下軟失敗判斷不完整)。建議維運者一次檢視整份 Tomcat 安全公告再排定更新,而不是只針對 CVE-2026-87022 單獨修補,以免遺漏同批次修復的其他問題,畢竟這幾顆漏洞都指向 WebSocket 與 HTTP/2 這類長連線處理的邊界判斷。
若短期內無法立即升級,權宜作法是在 WebSocket 升級階段直接拒絕協商 permessage-deflate 延伸,讓連線退回未壓縮模式。停用壓縮可以完全繞開這個成因,代價是原本靠壓縮節省的頻寬會暫時消失,需要自行評估流量成本。