rustls 0.23.46 修四則漏洞,含 PQ 降級
RustSec Advisory Database · 2026-10-14
rustls 在 0.23.46 一次補上四個彼此無關的缺口,其中最值得看的是 client 在伺服器尚未通過驗證時就記下它選的金鑰交換群組,讓攻擊者能把後續連線壓回只有 X25519 的傳統金鑰交換。四則公告 RUSTSEC-2026-0346 到 RUSTSEC-2026-0349 皆於 2026-10-14 發布,修補版本都是 >=0.23.46,嚴重度為 CVSS 2.3 到 4 之間的 LOW 與 MEDIUM。
降級至傳統金鑰交換(RUSTSEC-2026-0349)
RUSTSEC-2026-0349(GHSA-w44r-93j7-qv28,CVSS 3.7)出在 key share 預測。client 處理 ServerHello 時,會依 server name 記錄伺服器選了哪個金鑰交換群組,用來猜下次 ClientHello 該送哪個 key share,但這筆紀錄是在伺服器驗證之前寫入的。
網路上的攻擊者只要對某次連線回一個選定 X25519 的 ServerHello,然後斷線。之後對同一個 server name 的 ClientHello 只帶 X25519 的 key share,supported_groups 卻仍把 X25519MLKEM768 排第一。如果真正的伺服器直接接受這個 share,而不是回 HelloRetryRequest 要求混合群組,握手就會在沒有任何錯誤的情況下以純傳統金鑰交換完成。
- 後果是失去後量子保密性,也就是「先存後解」的風險;公告明講沒有金鑰外洩,也沒有驗證繞過。
- 紀錄會留在 client 的 session store 中,持續到該筆條目被淘汰為止。
- 不受影響:伺服器會對偏好群組回 HelloRetryRequest 的連線、關閉 resumption 的 client(因為什麼都不存)、其他 server name。
公告也指出此行為在 draft-ietf-tls-key-share-prediction 有討論,實際影響很大程度取決於伺服器政策。
ECH 被拒後外送緩衝資料(RUSTSEC-2026-0347)
RUSTSEC-2026-0347(GHSA-vp88-798v-h67f,CVSS 2.3)處理 Encrypted Client Hello 被伺服器拒絕的情況。此時 client 用外層 ClientHello 完成握手,並對 ECH config 的 public_name 驗證伺服器。問題在於 rustls 會先把透過 ClientConnection::writer() 緩衝的應用層資料加密排進佇列,才排 ech_required alert。
結果是應用程式雖然收到 Error::PeerIncompatible(ServerRejectedEncryptedClientHello),下一次 write_tls() 為了送出 alert,也會把原本要給內層伺服器的明文送給 public_name 那台前端伺服器。這違反 RFC 9849 第 6.1.6 節「送出任何應用資料之前必須先以 ech_required 中止」的要求。
受影響的只有同時符合三項條件的 client:使用 EchMode::Enable(GREASE ECH 不受影響)、在握手完成前就寫入資料、連到會拒絕其 ECH config 的伺服器(例如 config 過期)。公告說明,這個順序問題更早就存在,但 0.23.44 之前 client 是用內層 server name 驗證憑證,驗證會先失敗,資料不會送出;所以 <0.23.44 標為不受影響。
另外兩則
RUSTSEC-2026-0348(CVSS 3.7):內建 Brotli 憑證解壓縮器雖然限制了輸出大小,卻接受對端指定的 history window,且啟用了 large-window 擴充,五個位元組的標頭就能觸發 1 GiB 配置,配置失敗的行程會直接中止,攻擊者不需要受信任憑證。只有啟用非預設 brotli feature 的 client(連到惡意伺服器)與會要求 client 憑證的 server 受影響,<0.23.9 不受影響。
RUSTSEC-2026-0346(CVSS 4,MEDIUM):Tls12ClientSessionValue 與 Tls13ClientSessionValue 的 Debug 是 derive 出來的,會印出 TLS 1.2 master secret 或 TLS 1.3 resumption PSK。這是四則裡唯一不需要網路攻擊者的:自訂 ClientSessionStore 若用 {:?} 記錄這些值,密鑰就會進 log。內建 session cache 與一般連線的 Debug 已做遮蔽,不受影響;<0.21.0 不受影響。
影響範圍
四則都不是遠端程式碼執行,但各自踩到不同的信任假設:未驗證的資料不該改變之後的行為,密鑰不該出現在 log,驗證失敗前不該送出明文。
| 公告 | 誰要檢查 | 不受影響的版本 |
|---|---|---|
0346 | 自訂 ClientSessionStore 並以 Debug 輸出的程式 | <0.21.0 |
0347 | 啟用 EchMode::Enable 且握手前寫資料的 client | <0.23.44 |
0348 | 啟用 brotli feature 的 client,或要求 client 憑證的 server | <0.23.9 |
0349 | 長時間存活、保留 session store 的 client | 未列出 |
實務上先看 cargo tree -i rustls 確認實際解析到的版本,再升到 0.23.46 以上。若暫時不能升級,ECH 的受影響者可在握手完成前不要寫入資料,Brotli 的受影響者可關閉 brotli feature,自訂 session store 則不要對 session value 做 Debug 輸出。這些暫時作法是依公告描述的觸發條件推出,公告本身只列出修補版本。
原始來源:RUSTSEC-2026-0346、RUSTSEC-2026-0347、RUSTSEC-2026-0348、RUSTSEC-2026-0349