CVE-2026-16028:Perl 的 Protocol::HTTP2 模組讓已關閉的 HTTP/2 串流永久佔用記憶體
oss-security 郵件論壇 · 2026-09-07
CVE-2026-16028 於 2026 年 9 月 7 日透過 oss-security 郵件論壇公開,受影響的是 Perl 生態系中實作 HTTP/2 協定的模組 Protocol::HTTP2。低於 1.14 版的模組在串流(stream)進入關閉狀態後,不會將對應的資料結構從連線層的串流表中移除,導致長連線在持續互動下記憶體用量單調上升,形成可被遠端觸發的記憶體耗盡型阻斷服務(DoS)。
漏洞機制
HTTP/2 協定以獨立的串流承載每一次請求與回應,每個串流都有一組遞增的識別碼與生命週期狀態機,從 IDLE、OPEN、HALF_CLOSED 一路走到 CLOSED。在 Protocol::HTTP2 的實作中,負責狀態轉換的 stream_state 函式,一旦偵測到串流進入 CLOSED,會歸還併行串流計數的名額並清除大部分暫存資料,但該串流在連線的串流表中的條目本身從未被刪除。
由於 HTTP/2 的串流識別碼在同一條連線上只會遞增、不會重複使用,攻擊者只要在單一連線上反覆開啟並立刻關閉串流,每一次關閉都會在雜湊表裡留下一筆殘影。標準定義的 SETTINGS_MAX_CONCURRENT_STREAMS 參數只限制同時存活的串流數量,對已關閉但仍賴著不走的歷史條目完全無感,因此無法作為天然的防線。
公告中估算,每個殘留的關閉串流條目約消耗 920 位元組記憶體;若攻擊者在一條連線上依序開關 10 萬個串流,伺服器端就會多背負約 88 MiB 的額外記憶體開銷,且此增長沒有上限,直到連線被關閉或行程被系統終止為止。此問題被歸類為 CWE-401(物件生命週期結束後未釋放記憶體)。
受影響版本
- Protocol::HTTP2(CPAN 發行名稱 Protocol-HTTP2)
1.14之前所有版本 - 修補版本:
1.14及之後版本
修補與緩解
官方修補提交(commit 27a488a)替連線物件新增了 closed_streams 佇列與 max_closed_streams 上限(預設 PH2_MAX_CLOSED_STREAMS = 65535),每次有串流進入 CLOSED,識別碼就被推進佇列;一旦佇列長度超過上限,最舊的關閉串流會被強制從串流表中剔除,即使這已是對 HTTP/2 標準字面定義的一種妥協。
push @{ $self->{closed_streams} }, $stream_id;
delete $self->{streams}->{ shift @{ $self->{closed_streams} } }
if @{ $self->{closed_streams} } > $self->{max_closed_streams}對於暫時無法升級的使用者,公告建議的緩解方式是限制單一連線可處理的請求數並主動關閉重建,這樣舊連線的串流表會隨連線一起被釋放,不會無限增長。此漏洞由 CPAN Security Group 的 Robert Rothenberg 提交報告,修補內容已同步發布於 MetaCPAN 上 Protocol-HTTP2-1.14 的 changes 紀錄。
CVE-2026-86287:Net::IP::LPM 前綴長度驗證失守,允許清單與封鎖清單雙雙失靈
oss-security 郵件論壇 · 2026-09-07
CVE-2026-86287 同樣於 2026 年 9 月 7 日在 oss-security 上公開,問題出在 Perl 模組 Net::IP::LPM——一個實作「最長前綴匹配」(longest-prefix-match, LPM)查表、常被用來做 IP 允許清單或封鎖清單比對的模組。低於 1.12 版的模組沒有驗證前綴長度(prefix length)輸入是否為合法整數,導致畸形輸入會被靜默轉換成 0,讓原本精確的規則變成「比對所有位址皆成立」的萬用規則。
漏洞機制
LPM 查表的原理是替每一筆規則附加一個前綴長度,決定要比對 IP 位址的前幾個位元;IPv4 合法範圍是 0 到 32,前綴長度愈小代表比對範圍愈廣,而 0 正是最極端的情況——形同「比對任何位址都算命中」的預設路由。公告指出 Net::IP::LPM 對前綴長度的處理有兩個獨立錯誤:非數字或非 ASCII 輸入會被當成 0 處理,而超過 2**31 的整數則會被靜默截斷。
根源出在模組的 C 語言繫結層。LPM.xs 原本把 prefix_len 宣告為 C 語言的 int(在多數平台上只有 32 位元寬),Perl 層呼叫時也未曾檢查輸入值的型別與數值範圍。只要應用程式把設定檔、API 參數或其他不受信任的輸入直接餵給 add(),一個打錯字的前綴長度或超大數值就能悄悄變成 0,不會拋出任何錯誤或警告。
影響方向取決於規則清單的用途:如果是允許清單(allow-list),一筆本該只放行單一子網段的規則會變成放行所有位址;如果是封鎖清單(deny-list),同樣的錯誤則會讓整個規則變成擋下所有流量。兩種情境都是因為同一個底層瑕疵,只是造成的資安後果方向相反——一個是存取控制形同虛設,另一個是服務直接對所有正常流量斷線。
受影響版本
- Net::IP::LPM(CPAN 發行名稱 Net-IP-LPM)
1.12之前所有版本 - 修補版本:
1.12及之後版本
值得一提的是,這個模組近期的變更紀錄中已修過至少兩個同類型問題——CVE-2026-56015(前綴長度未做邊界檢查)與 CVE-2025-40910(位址解析邏輯的回退修正),顯示前綴與長度的輸入驗證在這個模組裡是反覆出現的弱點類別,而非單一疏漏。
修補與緩解
修補提交同時處理了 Perl 層與 C 層。Perl 端的 add() 函式新增了明確檢查:位址字串必須先能被 inet_pton 解析成功,且前綴長度字串必須完全符合 ^[0-9]+$ 的十進位數字格式,否則直接 croak 中止。
croak "invalid prefix address '${prefix}'" unless defined $prefix_bin;
...
croak "prefix length must be a decimal integer"
unless $prefix_len =~ /^[0-9]+$/;C 層則把 LPM.xs 與 lpm_lib.c 中的 prefix_len 參數型別從 int 改成 Perl 原生的 IV(與平台字長一致的整數型別),從根本上避免 32 位元截斷造成的數值繞回。此修補由模組維護者暨 CPAN Security Group 成員 Robert Rothenberg 提交,並同步發布於 Net-IP-LPM-1.12 的 changes 紀錄。
greentic-setup 與 greentic-setup-dev 遭植入惡意程式:VS Code 開啟專案即觸發 PolinRider 變種
RustSec Advisory Database · 2026-09-07
RUSTSEC-2026-0280 與 RUSTSEC-2026-0281 於 2026 年 9 月 7 日由 RustSec Advisory Database 公告,涉及 Rust 生態系 Greentic 專案下的兩個姊妹套件——greentic-setup 與 greentic-setup-dev。兩者都在 2026 年 9 月 6 日各自被上傳了一個含惡意程式碼的版本,約 27 小時後在 Nextron Systems GmbH 研究團隊通報下被 crates.io 下架,這是一起同時針對兩個關聯套件的供應鏈攻擊事件,而非單純的程式錯誤。
漏洞機制
兩份公告描述的手法一致:惡意版本內含PolinRider 惡意程式的變種,會在「依賴該套件的專案於 Visual Studio Code 中被開啟時」觸發執行。公告本身沒有進一步說明啟動路徑的實作細節,但從套件名稱與定位推測,greentic-setup、greentic-setup-dev 屬於專案初始化與開發環境設定用途的套件,這類套件通常擁有執行建置腳本或寫入專案設定檔的正當理由,也因此更容易被用來夾帶會在開發者機器上自動執行的程式碼。
兩個惡意版本的版本號都相當反常:greentic-setup-dev 的惡意版本是 1.3.34027618345,greentic-setup 則是 1.3.1-dev.34027618345,兩者都嵌入了一串異常龐大的數字。這類刻意拉高版本號的手法在套件生態系的供應鏈攻擊中並不少見,目的是讓套件管理工具在解析相依版本時優先選中這個惡意版本,而非維護者原本發布的正常版本。
公告也指出下游波及範圍:greentic-setup 被 greentic-start、greentic-start-dev、greentic-operator、greentic-operator-dev 四個 Greentic 生態系套件所依賴;greentic-setup-dev 則沒有任何套件相依於它。兩份公告都表明目前沒有證據顯示惡意版本曾被實際下載使用,但仍提醒 Greentic 使用者主動檢查自己的系統。
受影響版本
greentic-setup-dev:僅1.3.34027618345這一個版本受影響(RUSTSEC-2026-0280)greentic-setup:僅1.3.1-dev.34027618345這一個版本受影響(RUSTSEC-2026-0281)- 其餘不論該惡意版本之前或之後發布的版本,均被標記為未受影響
修補與緩解
兩份公告都標註「無修補版本」(no patched versions),這與一般漏洞公告不同,因為問題並非程式邏輯缺陷需要修正,而是整個版本本身就是惡意植入,因此因應方式是直接由 crates.io 下架,而非等待新版修補。crates.io 對已發布版本採取的是 cargo yank 機制:被 yank 的版本不會再被全新的相依解析選中,但版本本身的原始碼與 Cargo.lock 中已鎖定該版本的既有專案理論上仍可繼續存取,這也是公告特別提醒使用者主動檢查、而非假設下架等於清除的原因。
從發布到下架之間的約 27 小時空窗,是這起事件裡除了下游波及套件數之外唯一被公開的時間量化資訊。兩份公告皆由 Nextron Systems GmbH 的研究團隊通報,並以 CC0-1.0 授權公開發布。