libpng 1.6.59 修補 zlib 殘留指標 UAF(CVE-2026-46675)
oss-security(Cosmin Truta)· 2026-09-29
libpng 在 zTXt、iTXt、iCCP 三種 chunk 解壓完畢後,會釋放 zlib stream 卻不清掉 next_in 與 avail_in,讓後續的 png_read_end 拿著已失效的指標繼續解壓。1.6.59 補上這個清理動作,修掉自 1.6.0 就存在的 use-after-free。
公告編號 CVE-2026-46675,CVSS 3.1 為 5.9(Medium),於 2026-09-29 隨 v1.6.59 發布。
漏洞機制
libpng 讀取這三種壓縮 chunk 時,會借用 png_ptr->zstream 做解壓。處理完畢後 chunk handler 釋放了 stream,卻沒有把輸入指標與長度歸零,zstream 裡仍留著指向舊緩衝區的位址。
觸發條件是應用程式呼叫 png_read_info 之後,沒有讀任何 image row 就直接呼叫 png_read_end。此時 png_read_end 會從那個殘留指標「接續」解壓,讀到已釋放的記憶體。
| 變體 | 殘留指標指向 | 類型 |
|---|---|---|
| zTXt / iTXt | libpng 的 chunk read buffer | heap use-after-free |
| iCCP | png_handle_iCCP 的區域陣列 | stack use-after-return |
受影響版本與實際衝擊
- 受影響:
1.6.0至1.6.58 - 修正:
1.6.59
公告明確說衝擊有限:懸空指標只被讀取,解壓出的資料寫入會被丟棄的暫存緩衝區,因此可能後果是應用程式崩潰,公告未提到資料外洩或記憶體損毀。這也解釋了為何評分只有 Medium。
真正會踩到的是「先讀 metadata、跳過像素」的程式,例如只想取得 PNG 內嵌文字或 ICC profile 的縮圖產生器、檔案類型掃描器、上傳檢查服務。只要它們呼叫 png_read_info 後直接 png_read_end,又處理不受信任的 PNG,攻擊者就能用帶有上述 chunk 的檔案讓服務崩潰。正常讀完所有 row 才呼叫 png_read_end 的流程,不在公告描述的觸發路徑內。
修補方式
修正 commit aa77ef3 只動 pngrutil.c(19 行新增、14 行刪除),新增 png_inflate_detach_buffers(),在取得與釋放 inflate stream 時都清掉輸入與輸出緩衝區的指標與計數:
static void png_inflate_detach_buffers(png_structrp png_ptr) {
png_ptr->zstream.next_in = NULL;
png_ptr->zstream.avail_in = 0;
...清成 NULL 與 0 之後,即使 png_read_end 在沒讀 row 的情況下被呼叫,zlib 也沒有舊位址可讀。
該檢查什麼
- 發行版套件維護者與自行打包 libpng 的專案:升到
1.6.59,或 backport 上述 commit。 - 靜態連結 libpng 的產品(圖片處理服務、GUI 工具、嵌入式韌體):光升級系統套件不夠,要重新編譯。
- 自己呼叫 libpng API 的程式:搜尋
png_read_end的呼叫點,確認是否可能在沒讀 row 時走到。這只能降低風險,不能取代升級。
另外,Sam James 在同一串討論中指出,他在 SourceForge 的 libpng16 目錄與 libpng.download/src 都找不到 1.6.59 的 tarball,並詢問專案是否改用 GitHub 自動產生的 release 封存(該封存不保證穩定、也無法簽章)。截至該信件,官方尚未在串中回覆,發行版打包者取得原始碼時需留意這點。
發現者:Ze Sheng(O2Lab 與 AISLE),iCCP 變體另由 @JasonHonKL 獨立回報。
原始來源:oss-security 公告、GHSA-qvg3-h654-xq3j、修正 commit、Sam James 回信