1. 簡介

PixelSmash 漏洞(編號 CVE-2026-8461)是 FFmpeg 多媒體處理框架中 MagicYUV 解碼器的一個重大安全缺陷。作為現代數位媒體基礎建設的核心元件,FFmpeg 被廣泛應用於各種軟體,從消費級影音播放器到企業級雲端轉碼服務。此堆積越界寫入漏洞(Out-Of-Bound, OOB)的發現,凸顯了複雜 Codec 實作中持續存在的風險,即使是數學邏輯上的細微不一致,也可能導致系統完全被攻陷。此報告針對漏洞的根本成因、利用機制以及對軟體供應鏈安全的廣泛影響,提供了全面的技術調查 [1]

AVBuffer 結構體暗藏致命弱點?PixelSmash 如何用 OOB 劫持 FFmpeg 的 free 指標! | 資訊安全新聞

2. FFmpeg 架構與 Codec 基礎

要理解 PixelSmash,必須先了解 FFmpeg 如何處理影片解碼,特別是在 YUV 色彩空間和基於使用 slice 的處理方面。與 RGB 模型不同,YUV 將亮度(Luma, Y)與色彩資訊(Chroma, U 和 V)分離。在許多壓縮方案中,會採用色度抽樣(chroma subsampling)來減少資料大小,例如 YUV420P 格式,其色度平面的解析度在兩個維度上均為亮度平面的一半。

在影像處理中,「slice」是指一個 frame 中可獨立解碼的水平分割區域。這種架構有助於平行處理,但也增加了記憶體管理的複雜性。解碼器必須精確計算每個 slice 在多個平面上的目的指標(Destination pointer)。當這些 slice 的尺寸與已配置的緩衝區大小不完全吻合時,尤其是在抽樣操作期間,記憶體損毀的風險便會顯著增加 [2]

3. 技術根本原因:進位不一致

PixelSmash 漏洞的核心在於 frame 配置器(Allocator)與 MagicYUV 解碼器(Decoder)之間的進位不一致。在處理已抽樣的影片(Subsampled video)時,解碼器必須將亮度列的索引轉換為色度列的索引。這通常透過右移運算來達成。然而,MagicYUV 解碼器的特定實作中,對於 slice 高度使用了「ceil」進位的右移(AV_CEIL_RSHIFT)。

當攻擊者提供一個具有奇數 slice 高度的惡意媒體檔案時,ceil 進位的計算結果會導致每個 slice 多計算一列。儘管 frame 配置器(位於 get_buffer.c)是根據對齊後的 frame 尺寸來配置記憶體,但解碼器(位於 magicyuv.c)會跨多個 slice 累積這些額外列。這種累積最終會將寫入指標推到已配置的色度緩衝區邊界之外。

4. 解碼過程的序列分析

下方序列圖說明了在處理惡意 frame 事件期間,bitstream 解析器(Parser)、記憶體配置器(Allocator)和解碼器(Decoder)之間的互動。

sequenceDiagram participant B as Bitstream Parser participant A as Frame Allocator (get_buffer.c) participant D as MagicYUV Decoder (magicyuv.c) participant H as Heap Memory B->>D: Provide crafted slice_height (e.g., 31) D->>A: Request buffer for 32x32 frame A->>H: Allocate 16 rows for Chroma plane (32/2) Note over A,H: Buffer size = 16 * stride D->>D: Calculate sheight = AV_CEIL_RSHIFT(31, 1) = 16 D->>D: Process Slice 0 (Rows 0-15) D->>H: Write 16 rows to Chroma buffer D->>D: Calculate Offset for Slice 1: j * sheight = 1 * 16 D->>H: Write to Row 16 (OOB WRITE) Note right of H: Corruption of adjacent AVBuffer struct

5. 詳細程式碼分析

此漏洞可追溯至主要研究 [1] 中提出的 FFmpeg 原始碼的五個關鍵部分。

5.1. 輸入獲取

漏洞始於解碼器從 bitstream 讀取一個由攻擊者控制的 32 位元整數,用以定義 slice 高度。

  1. /*
  2. * magicyuv.c:550
  3. * The decoder retrieves the slice_height directly from the LE32 bitstream.
  4. * There is no immediate validation to ensure this value aligns with
  5. * the vertical subsampling requirements of the chosen pixel format.
  6. */
  7. s->slice_height = bytestream2_get_le32u(&gb);

5.2. 進位邏輯差異

每個 slice 的色度列數計算使用了 ceil 進位右移,這是造成溢位的關鍵因素。

  1. /*
  2. * magicyuv.c:275
  3. * AV_CEIL_RSHIFT(31, 1) returns 16.
  4. * If the total height is 32 and slice_height is 31, the decoder
  5. * incorrectly assumes each slice requires 16 chroma rows.
  6. */
  7. int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[1]);

5.3. 指標計算

後續 slice 的目的指標是使用錯誤的 slice 高度來計算。

  1. /*
  2. * magicyuv.c:287
  3. * For the second slice (j=1), the destination pointer is calculated as:
  4. * base_pointer + (1 * 16 * stride).
  5. * Since the buffer only has 16 rows (0-15), row 16 is out of bounds.
  6. */
  7. dst = p->data[1] + j * sheight * stride;

5.4. 越界寫入

實際的記憶體損毀發生在緩衝區複製操作期間,此時攻擊者控制的資料會被寫入計算出的越界位址。

  1. /*
  2. * magicyuv.c:291-294
  3. * In raw decoding mode, bytes are copied directly from the bitstream
  4. * to the destination pointer. This allows for precise heap corruption.
  5. */
  6. for (k = 0; k < height; k++) {
  7. bytestream_get_buffer(&slice, dst, width);
  8. dst += stride;
  9. }

5.5. 透過 AVBuffer 劫持進行攻擊

溢位鎖定 AVBuffer 結構,該結構包含一個用於記憶體釋放的函式指標。

  1. /*
  2. * libavutil/buffer.c:133
  3. * When a frame is unreferenced, FFmpeg calls the 'free' function pointer.
  4. * By overwriting 'buf->free' with system() and 'buf->opaque' with a command,
  5. * the attacker achieves arbitrary code execution.
  6. */
  7. buf->free(buf->opaque, buf->data);

6. 緩解措施與比較

傳統的緩衝區溢位通常源於字串操作時缺乏邊界檢查,例如不當使用 strcpy [2] 。相比之下,PixelSmash 是一種更為複雜的「語意」溢位,其邊界檢查雖存在但數學計算有誤。儘管一般的緩衝區溢位防禦策略強調輸入驗證和使用如 Rust 等安全的程式語言 [2] ,PixelSmash 案例顯示,即使在成熟的 C 語言程式碼庫中,不同模組(配置器 vs. 解碼器)之間的互動仍可能產生隱藏的漏洞。

PixelSmash 的修補方式是在 libavcodec/magicyuv.c 中新增了七行程式碼,以嚴格驗證 slice_height 是否與垂直抽樣和交錯參數相容。這確保了解碼器所使用的進位邏輯不會超出 frame 配置器所建立的記憶體邊界。

7. 結論

PixelSmash 漏洞強烈提醒了我們多媒體處理軟體固有的複雜性。透過利用 MagicYUV 解碼器中一個細微的進位錯誤,攻擊者能從單純的堆積溢位發展為完整的遠端程式碼執行。此研究強調了進行全面性安全審查的必要性,這種審查不應僅檢視個別函式,還必須檢視資料在整個軟體框架中流動的數學一致性。由於 FFmpeg 仍是全球數位生態系統的關鍵依賴,對其多樣化的 Codec 程式庫進行修補和主動審計,對於維護軟體供應鏈的完整性至關重要。