| パッケージ | 影響を受けるバージョン | 修正済みバージョン |
|---|---|---|
| SixLabors.ImageSharp | ≥ 3.0.0, < 3.2.0≥ 4.0.0, < 4.1.1 | 3.2.04.1.1 |
When decoding a tiled TIFF with fax compression (T4/T6/MH), DecodeTilesChunky allocates each tile buffer from TileWidth (ceil(TileWidth*bpp/8)*TileLength bytes) but constructs the fax decompressor with frame.Width: TiffDecompressorsFactory ignores the isTiled/tileWidth/tileHeight parameters entirely. The T4/T6/MH decompressors treat the full image width as the scanline length and advance (and really write, via read-modify-write bit ops) frame.Width bits per row, with no bounds check against the tile buffer. The very first tile therefore writes linearly out of bounds — about ImageWidth/8 bytes per row × TileLength rows into a TileWidth-sized buffer. With ImageWidth=4,000,000, TileWidth=16, TileLength=16 this writes ~2 MB past a 32-byte buffer and kills the process deterministically; a T6 all-white variant advances the bit offset by >512 MB silently, showing an alarm-free heap-corruption window for the same defect. A crafted file fully controls the OOB length per tile and works with perfectly legal per-row run codes (no overlong runs needed).
Verified at commit 5cd4d0d26a82a9549f297a237aea9cf665bddff8 (main; latest release v4.1.0, the supported major).
Root cause: a size mismatch between tile buffer allocation and decompressor width, because the factory drops the tile parameters.
bytesPerTileRow = RoundUpToMultipleOfEight(tileWidth*bitsPerPixel); tile buffer = bytesPerTileRow*tileLength bytes (32 bytes in the PoC)CreateDecompressor<TPixel>(frame.Width, ..., isTiled: true, tileWidth, tileLength) passes the full frame widthwidth (= frame.Width); isTiled/tileWidth/tileHeight ignoredこれらの製品をお使いですか?サイトをスキャンして、脆弱なバージョンが公開されていないか確認しましょう。
無料でサイトをスキャンT6TiffCompression.cs#L76-L108this.widthBitWriterUtils.WriteBitsTiffDecoderCore.cs:829-831bytesPerTileRowAttack surface: Image.Load(stream) on an attacker-supplied tiled TIFF (TiffDecoderCore.DecodeImageWithTiles → DecodeTilesChunky). Default configuration; only requirement is a standard tiled TIFF header (TileWidth=16, TileLength=16) + Compression=3 (T4; T6 also constructible).
Suggested remediation:
isTiled, construct the T4/T6/MH decompressor with tileWidth (not frame width), or clip row writes to the caller-provided buffer length.BitWriterUtils (pass remaining bits), and validate every fax row advance against buffer capacity on both tiled and strip paths.WriteBit).Full PoC posted as the first comment below: Program.cs (driver), poc-tiled-t4.tif (crafted file, ~9.8 KB, base64 inline), README.
Build a small console project referencing src/ImageSharp/ImageSharp.csproj and run it against the crafted file (or call Image.Load on it from any host).
Observed with ImageWidth=4,000,000, TileWidth=16, TileLength=16, T4 with 400 makeup codes + EOL per row:
tile payload 9642 bytes; rows write ~2,048,000 bytes into a 32-byte buffer
Fatal error. System.AccessViolationException: Attempted to read or write protected memory.
at SixLabors.ImageSharp.Formats.Tiff.Compression.BitWriterUtils.WriteBits(Span`1<Byte>, IntPtr, IntPtr, Byte)
at ...T4TiffCompression.WritePixelRun(...)
at ...T4TiffCompression.Decompress(...)
Aborted (core dumped); exit=134
Controls: the same file with Compression=None decodes normally (container is fine); a T6 all-white-rows variant advances >512 MB of bit offset without a real write (silent corruption window) before tripping on a directory-level TileOffsets count check.
Reported by Kimi Security Team ([email protected]).