LibTIFF TIFF2PDF TIFFTAG_JPEGTABLES Remote Code Execution Vulnerability(CVE-2016-5652)

ID SSV:96666
Type seebug
Reporter Root
Modified 2017-10-12T00:00:00



An exploitable heap based buffer overflow exists in the handling of TIFF images in LibTIFF's TIFF2PDF tool. A crafted TIFF document can lead to a heap based buffer overflow resulting in remote code execution. Vulnerability can be triggered via a saved TIFF file delivered by other means.

Tested Versions

LibTiff - 4.0.6

Product URLs

CVSSv3 Score

6.4 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:L/A:L


This vulnerability is present in the Tiff2PDF tool that is bundled with LibTIFF. this tool is installed by default in the standard build process.

There exists a vulnerability in the parsing and handling of TIFF images. A specially crafted TIFF image file can lead to an out of bounds write and ultimately to remote code execution.

Tiff offers support for multiple compression algorithms inside of the image itself. One such algorithm is the JPEG compression. Looking at an information dump of the attached trigger we can see this is the compression algorithm used. TIFF Directory at offset 0x13a (314) Image Width: 32 Image Length: 16 Tile Width: 32 Tile Length: 1 [0] Bits/Sample: 4 Compression Scheme: JPEG Photometric Interpretation: min-is-black Rows/Strip: 1 Planar Configuration: single image plane JPEG Tables: (114 bytes)

Note also this is a tiled tiff [0], and the crash that happens when running the trigger is shown below. ``` rax = 0x0000000100b07f90 rbx = 0x0000000100993b60 rcx = 0x0000000000000010 rdx = 0xffffffffffffffe2 rdi = 0x0000000100b07fa0 rsi = 0x0000000100a72fd0 rbp = 0x00007fff5fbff830 rsp = 0x00007fff5fbff830 r8 = 0x0000000000000040 r9 = 0x00007fff7ae01110 __sFX + 240 r10 = 0xffffffffffffffff r11 = 0x0000000000095010 r12 = 0x0000000100b07f90 r13 = 0x0000000000000000

libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell: -> 0x7fff939be09a <+378>: vmovups ymmword ptr [rdi + rdx + 0x60], ymm4 0x7fff939be0a0 <+384>: pop rbp 0x7fff939be0a1 <+385>: vzeroupper 0x7fff939be0a4 <+388>: ret 0x7fff939be0a5 <+389>: nop word ptr cs:[rax + rax] 0x7fff939be0b0 <+400>: sub rsi, 0x8 0x7fff939be0b4 <+404>: mov rcx, qword ptr [rsi] 0x7fff939be0b7 <+407>: sub rdi, 0x8

  • thread #1: tid = 0x16c8c4, 0x00007fff939be09a libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 378, queue = '', stop reason = EXC_BAD_ACCESS (code=1, address=0x100b08000)
  • frame #0: 0x00007fff939be09a libsystem_platform.dylib_platform_memmove$VARIANT$Haswell + 378 frame #1: 0x00000001001614f1 libtiff.5.dylib_TIFFmemcpy(d=<unavailable>, s=<unavailable>, c=<unavailable>) + 65 at tif_unix.c:340 frame #2: 0x000000010001b1f8 llopt2p_readwrite_pdf_image_tile(t2p=&lt;unavailable&gt;, input=0x0000000100993b60, output=0x00000001009b5bc0, tile=1) + 4840 at tiff2pdf.c:2951 frame #3: 0x000000010000681f llopt2p_write_pdf(t2p=0x00000001009913f0, input=0x0000000100993b60, output=0x00000001009b5bc0) + 8143 at tiff2pdf.c:5553 frame #4: 0x00000001000037f7 llopmain(argc=&lt;unavailable&gt;, argv=&lt;unavailable&gt;) + 8439 at tiff2pdf.c:808 frame #5: 0x00007fff909705ad libdyld.dylibstart + 1 ```

The vulnerability arises in the calculating of the images tile size. The code uses a separate size reading function called t2preadtiffsizetile. The relevant code is shown below: if(t2p-&gt;tiff_compression==COMPRESSION_JPEG) { uint32 count = 0; if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt)!=0){ if(count &gt; 4){ k = checkAdd64(k, count, t2p); k -= 2; /* don't use EOI of header or SOI of tile */ } } }

Our files compression is indeed jpeg so this code block is hit. The vulnerability comes when the size variable, k, is decremented by 2. Above we see that the JPEG tables of our image are 114 bytes and by decrementing by 2 it is moving it to 112. Due to malloc rounding on OS X, 112 will not be rounded and a buffer of exact size is used. Relevant code to when the jpeg is read in is below. buffer= (unsigned char*) _TIFFmalloc(t2p-&gt;tiff_datasize); [0] if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory " "for t2p_readwrite_pdf_image_tile, %s", (TIFF_SIZE_T) t2p-&gt;tiff_datasize, TIFFFileName(input)); t2p-&gt;t2p_error = T2P_ERR_ERROR; return(0); } if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) { [1] if (count &gt; 0) { printf("COUNT:[%d]", count); _TIFFmemcpy(buffer, jpt, count); [2] bufferoffset += count - 2; table_end[0] = buffer[bufferoffset-2]; table_end[1] = buffer[bufferoffset-1]; }

The vulnerable buffer is allocated based on the data size in the structure which is 112 as shown above [1]. When the call to get field is made for jpeg tables [2], it will return 114 as previously noted thus resulting in a 2 byte buffer overflow. This overwrite happens to be adjacent to another freed object thus corrupting the chunk but could also be used to turn this into full remote code execution.

Crash Information

``` Crashed thread log = : Dispatch queue: 0 libsystem_kernel.dylib 0x00007fff8c9e8f06 __pthread_kill + 10 1 libsystem_pthread.dylib 0x00007fff9018b4ec pthread_kill + 90 2 libsystem_c.dylib 0x00007fff8f4cb6e7 abort + 129 3 libsystem_malloc.dylib 0x00007fff8a22b396 szone_error + 626 4 libsystem_malloc.dylib 0x00007fff8a2215f4 tiny_free_list_remove_ptr + 289 5 libsystem_malloc.dylib 0x00007fff8a21ff94 szone_free_definite_size + 3094 6 libtiff.5.dylib 0x000000010e3c7120 TIFFWriteDirectorySec + 52432 (tif_dirwrite.c:896) 7 tiff2pdf 0x000000010e33883c t2p_write_pdf + 8172 (tiff2pdf.c:3648) 8 tiff2pdf 0x000000010e3357f7 main + 8439 (tiff2pdf.c:808) 9 libdyld.dylib 0x00007fff909705ad start + 1

log name is: ./crashlogs/_Users_t_Desktop_tiled-tiff-afl_tiff2pdfcrash_id:000022,sig:06,src:000675,op:havoc,rep:4.crashlog.txt

exception=EXC_CRASH:signal=6:is_exploitable=yes:instruction_disassembly=jae CONSTANT:instruction_address=0x00007fff8c9e8f06:access_type=:access_address=0x0000000000000000: The crash is suspected to be an exploitable issue due to the suspicious function in the stack trace of the crashing thread: ' szone_error ' ```


  • 2016-06-15 - Vendor Disclosure
  • 2016-10-25 - Public Release