python / python/cpython

lzma: unbounded dictionary-size allocation is a memory DoS (zipfile, tarfile, lzma.decompress)

オープン
#155,649 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

extension-modules type-security
主要言語
Python
スター
77.2k
フォーク
35.9k
PR マージ指標
PR 指標を取得中

説明

Bug: LZMA decompression accepts an attacker-controlled dictionary size with no bound, and liblzma allocates the full dictionary up front when a decompressor is created. A few bytes of input can therefore force a multi-gigabyte allocation (memory denial of service).

Attack surfaces (both reported by OSS-Fuzz, both public):

  • zipfile with an LZMA-compressed member: the 5-byte LZMA properties header in the member data declares the dictionary. A 1088-byte zip whose member declares a ~2 GiB dictionary OOMs the process. https://issues.oss-fuzz.com/issues/495472861
  • tarfile's compression-detection loop: a 13-byte input whose first byte is a valid LZMA-alone properties byte (0x66) and whose remaining bytes encode a ~4 GiB dictionary is tried as LZMA; liblzma allocates 4 GiB before failing. https://issues.oss-fuzz.com/issues/482161128

Also reachable directly: lzma.decompress() / LZMADecompressor(format=FORMAT_AUTO) on untrusted bytes, and LZMADecompressor(FORMAT_RAW, filters=[{"dict_size": ...}]).

Root cause: two gaps:

  1. parse_filter_spec_lzma() accepts any dict_size (up to UINT32_MAX) for raw LZMA1/LZMA2 filter chains; liblzma allocates that dictionary at decompressor creation.
  2. LZMADecompressor defaults memlimit to UINT64_MAX, so the FORMAT_ALONE/FORMAT_AUTO paths (where the header is parsed inside liblzma) are also unbounded.

Proposed fix (PR to follow):

  • Reject dict_size > LZMA_DICT_SIZE_MAX (1.5 GiB, liblzma's own maximum) in parse_filter_spec_lzma() with LZMAError.
  • Default the decompressor memlimit to LZMA_DICT_SIZE_MAX instead of UINT64_MAX (callers may still pass an explicit memlimit).

No legitimate streams are affected: liblzma presets cap at 64 MiB dictionaries, and 1.5 GiB is liblzma's own maximum supported dictionary size.

Reported by OSS-Fuzz (ClusterFuzz). Reproducers attached to the issues above.

Linked PRs
  • gh-155650

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

parse_filter_spec_lzma() と LZMADecompressor から始め、次に issue で説明されている zipfile と tarfile のパスを確認してください。リンクされている OSS-Fuzz の再現ケースを使用して、過大な辞書によって無制限の割り当てが発生しなくなったことを検証し、通常の LZMA ストリームと明示的な memlimit の動作が維持されていることも確認してください。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
security
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。