[하루한줄] CVE-2026-24450: LibRaw uncompressed_fp_dng_load_raw heap overflow 취약점

URL

Target

  • LibRaw 8dc68e2 commit

Explain

LibRaw는 디지털카메라의 RAW 이미지 파일을 처리하기 위한 오픈소스 C/C++ 라이브러리입니다.

LibRaw에서 DNG 파일을 지원하며 CVE-2026-24450는 DNG 파일 디코더 루틴에서 발생했습니다.

void LibRaw::uncompressed_fp_dng_load_raw()
{
    [...]
    tile_stripe_data_t tiles;
    tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, 
               libraw_internal_data.unpacker_data.order,
               libraw_internal_data.internal_data.input);

[1] INT64 allocsz = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) * 
                    INT64(tiles.tileHeight) * INT64(ifd->samples) * 
                    INT64(sizeof(float));
[2] if (allocsz > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
        throw LIBRAW_EXCEPTION_TOOBIG;

    if (ifd->sample_format == 3)
[3]     float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth * 
                                          tiles.tileHeight * ifd->samples, 
                                          sizeof(float));
    [...]

    for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight)
    {
        for (unsigned x = 0; x < imgdata.sizes.raw_width && t < (unsigned)tiles.tileCnt; 
             x += tiles.tileWidth, ++t)
        {
            libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET);
            size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight;
            size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth;

            size_t inrowbytes = colsInTile * bytesps * ifd->samples;
            int fullrowbytes = tiles.tileWidth *bytesps * ifd->samples;
            size_t outrowbytes = colsInTile * sizeof(float) * ifd->samples;

            for (size_t row = 0; row < rowsInTile; ++row)
            {
[4]             unsigned char *dst = fullrowbytes > int(inrowbytes) ? rowbuf.data():
                    (unsigned char *)&float_raw_image
                    [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples];

[5]             libraw_internal_data.internal_data.input->read(dst, 1, fullrowbytes);
                [...]
            }
        }
    }
}

DNG 파일은 TIFF 파일 포맷을 기반으로 하며 [1] allocsz 변수 계산에 사용되는 값은 아래 DNG 태그에서 가져옵니다.

  • tiles.tileWidth : TileWidth 또는 ImageWidth
  • tiles.tileHeight : TileLength 또는 RowsPerStrip
  • tiles.tileCnt : ceil(ImageWidth / TileWidth) * ceil(ImageLength / TileHeight)
  • ifd->samples : SamplesPerPixel

[1] INT64 타입 캐스팅을 사용하여 버퍼 크기를 계산하고 [2] 설정된 최대 메모리 제한 값과 비교합니다. 하지만, [3] 실제 메모리를 할당 과정에서는 INT64 타입 캐스팅을 적용하지 않아 취약점이 발생했습니다.

calloc( tiles.tileCnt * tiles.tileWidth * tiles.tileHeight * ifd->samples, sizeof(float) );

첫 번째 인자 연산 시 32bit로 계산되기 때문에 integer overflow를 트리거 하여 실제 필요한 size보다 작은 size로 float_raw_image 버퍼를 할당할 수 있습니다.

[4] fullrowbytes 변수는 타일 한 행의 전체 크기, inrowbytes 변수는 현재 타일 위치에서 실제로 처리해야 하는 행의 크기입니다.

현재 타일 위치에서 처리해야 하는 행의 크기가 전체 크기일 경우 [4] 조건식이 false가 되어, dstfloat_raw_image를 가리키게 됩니다.

이후 [5] float_raw_image 버퍼에 파일 데이터를 write 할 때 [3] integer overflow로 작게 할당하면 heap overflow를 트리거 할 수 있습니다.

추가로 float_raw_image 버퍼 index 계산 시 raw_widthraw_height를 통해 OOB Write가 가능합니다.

Patch

해당 취약점은 float_raw_image 버퍼 할당 시 검증에 사용된 allocsz 변수를 사용하도록 패치 되었습니다.

Reference



본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.