Bug class: Heap OOB read
Reproduction steps:
oiiotool poc.heic -o /tmp/out.jpeg
poc (download from google drive)
Environment:
- OS: Ubuntu 22.04
- OIIO version: master
There is a bug in the heif input functionality of OpenImageIO. Specifically, in HeifInput::seek_subimage() (src). A ImageSpec m_spec is constructed with width and height obtained as follows:
m_spec = ImageSpec(m_ihandle.get_width(), m_ihandle.get_height(), bits / 8,
TypeUInt8);
This uses the libheif ImageHandle::get_width/height() method, which returns the dimension of the heif image handle. These dimensions are later used in calls to HeifInput::read_native_scanline() to read the decoded image's plane buffers:
const uint8_t* hdata = m_himage.get_plane(heif_channel_interleaved,
&ystride);
if (!hdata) {
errorfmt("Unknown read error");
return false;
}
hdata += (y - m_spec.y) * ystride;
memcpy(data, hdata, m_spec.width * m_spec.pixel_bytes());
However, there is no guarantee that the dimensions returned by ImageHandle::get_width/height() match the size of the decoded image's planes. Instead, the decoded image's dimensions should be obtained with Image::get_width/height(channel) (src). The original intention of this usage pattern is to accommodate transformations in the heif file -- the dimensions from the ImageHandle are that of the untransformed image, while the dimensions from the Image are that of the transformed image. However, since the dimensions returned from ImageHandle are obtained by parsing the ispe (Image spatial Extents), it is possible for an attacker to forge the ispe values, which would create an ImageSpec with incorrect dimensions. In such a case, there would be an OOB read on the decoded plane data if the incorrect dimensions in the ImageSpec are trusted.
This is indeed the case in ImageInput::read_image(). Using this C++ example, I triggered an ASan fault with this poc. I crafted this poc by using a regular heic file and forging the values of its ispe dimensions from (1440, 960) to (14400, 9600). It is possible to get arbitrary OOB reads by specially crafting the heif file. This poc also crashes oiiotool. This specific command will crash it: oiiotool poc.heic -o out.jpeg (but really any operation that reads the entire image will work).
In the worst case, this can lead to an information disclosure vulnerability, particularly for programs that directly use the ImageInput APIs.
The fix should be quite simple: Create the ImageSpec as follows, using the Image::get_width/height() methods as mentioned earlier.
m_spec = ImageSpec(m_himage.get_width(heif_channel_interleaved),
m_himage.get_height(heif_channel_interleaved),
bits / 8, TypeUInt8);
Bug class: Heap OOB read
Reproduction steps:
oiiotool poc.heic -o /tmp/out.jpegpoc (download from google drive)
Environment:
There is a bug in the heif input functionality of OpenImageIO. Specifically, in
HeifInput::seek_subimage()(src). AImageSpec m_specis constructed with width and height obtained as follows:This uses the libheif
ImageHandle::get_width/height()method, which returns the dimension of the heif image handle. These dimensions are later used in calls toHeifInput::read_native_scanline()to read the decoded image's plane buffers:However, there is no guarantee that the dimensions returned by
ImageHandle::get_width/height()match the size of the decoded image's planes. Instead, the decoded image's dimensions should be obtained withImage::get_width/height(channel)(src). The original intention of this usage pattern is to accommodate transformations in the heif file -- the dimensions from theImageHandleare that of the untransformed image, while the dimensions from theImageare that of the transformed image. However, since the dimensions returned fromImageHandleare obtained by parsing the ispe (Image spatial Extents), it is possible for an attacker to forge the ispe values, which would create anImageSpecwith incorrect dimensions. In such a case, there would be an OOB read on the decoded plane data if the incorrect dimensions in theImageSpecare trusted.This is indeed the case in
ImageInput::read_image(). Using this C++ example, I triggered an ASan fault with this poc. I crafted this poc by using a regular heic file and forging the values of its ispe dimensions from (1440, 960) to (14400, 9600). It is possible to get arbitrary OOB reads by specially crafting the heif file. This poc also crashes oiiotool. This specific command will crash it:oiiotool poc.heic -o out.jpeg(but really any operation that reads the entire image will work).In the worst case, this can lead to an information disclosure vulnerability, particularly for programs that directly use the
ImageInputAPIs.The fix should be quite simple: Create the
ImageSpecas follows, using theImage::get_width/height()methods as mentioned earlier.