CVE-2016-5652
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.
LibTiff - 4.0.6
https://developer.apple.com/osx/download
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 = 'com.apple.main-thread', 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 llop`t2p_readwrite_pdf_image_tile(t2p=<unavailable>, input=0x0000000100993b60, output=0x00000001009b5bc0, tile=1) + 4840 at tiff2pdf.c:2951
frame #3: 0x000000010000681f llop`t2p_write_pdf(t2p=0x00000001009913f0, input=0x0000000100993b60, output=0x00000001009b5bc0) + 8143 at tiff2pdf.c:5553
frame #4: 0x00000001000037f7 llop`main(argc=<unavailable>, argv=<unavailable>) + 8439 at tiff2pdf.c:808
frame #5: 0x00007fff909705ad libdyld.dylib`start + 1
The vulnerability arises in the calculating of the images tile size. The code uses a separate size reading function called t2p_read_tiff_size_tile. The relevant code is shown below:
if(t2p->tiff_compression==COMPRESSION_JPEG) {
uint32 count = 0;
if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt)!=0){
if(count > 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->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->tiff_datasize,
TIFFFileName(input));
t2p->t2p_error = T2P_ERR_ERROR;
return(0);
}
if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) { [1]
if (count > 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.
Crashed thread log =
: Dispatch queue: com.apple.main-thread
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
Tyler Bohan