Apple Image I/O EXR Color Component Remote Code Execution Vulnerability(CVE-2016-4629)

2017-10-17T00:00:00
ID SSV:96730
Type seebug
Reporter Root
Modified 2017-10-17T00:00:00

Description

SUMMARY

An exploitable heap based buffer overflow exists in the handling of EXR images on OS X. A crafted EXR document can lead to a heap based buffer overflow resulting in remote code execution. Vulnerability can be triggered via a saved EXR file delivered by other means when opened in any application using the Apple Image I/O API.

TESTED VERSIONS

OSX El Capitan - 10.11.4

PRODUCT URLs

https://developer.apple.com/osx/download

CVSSv3 SCORE

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

DETAILS

This vulnerability is present in the Apple Image I/O API which is used for all image handling on OS X including rendering images in Preview.

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

OpenEXR is a high dynamic-range (HDR) image file format developed by Industrial Light & Magic for use in computer imaging applications and is used in all motion pictures currently in production. EXR uses 16-bit floating-point color component values. Since the IEEE-754 floating-point specification does not define a 16-bit format, EXR created the "half" format. Half values have 1 sign bit, 5 exponent bits, and 10 mantissa bits. This information is then read in as rows of x and y coordinates to draw the image. The vulnerability arises when the values read in are not properly sanitized.

The relevant code for the reading of the image is shown below.

``` for (int y = yStart; y <= maxYThisRow; y += toSlice.ySampling) { // Set the pointers to the start of the y scanline in // this row of tiles

fromPtr = fromSlice.base + (y - tileRange.min.y) * fromSlice.yStride + xStart * fromSlice.xStride;

toPtr = toSlice.base +
        divp (y, toSlice.ySampling) * toSlice.yStride +
        divp (xStart, toSlice.xSampling) * toSlice.xStride; [1]

// Copy all pixels for the scanline in this row of tiles

for (int x = xStart; x &lt;= levelRange.max.x; x += toSlice.xSampling)
{
  for (int i = 0; i &lt; size; ++i)
         toPtr[i] = fromPtr[i];

  fromPtr += fromSlice.xStride * toSlice.xSampling;
  toPtr += toSlice.xStride;
}

} ``` The problem here arises when toPtr is calculated, [1], and the values of xStride and yStride are user controlled. If these variables are signed it causes the resulting calculation to be sign extended and points the destination buffer out of bounds. Shown below is where the toPtr is calculated and the corresponding values.

``` RAX: 0xFFFFFFFFDEDEDE00 RBX: 0x00000000DEDEDE00 RBP: 0x00007FFF5FBFA200 RSP: 0x00007FFF5FBFA120 o d I t S z a p c RDI: 0x00000000DEDEDEDE RSI: 0x0000000000000002 RDX: 0x0000000196C68D20 RCX: 0xFFFFFE3242423620 RIP: 0x0000000168475097 R8: 0x0000000196C68D20 R9: 0x0000000000000002 R10: 0x00000000DEDEDEDE R11: 0x00000000DEDEDE00 R12: 0x0000000100000001 R13: 0x0000000000000002 R14: 0x0000000000000010 R15: 0x00000000DEDEDEDE

libOpenEXR.dylib`Imf_2_2::InputFile::readPixels: -> 0x168475097 <+1041>: imul rax, r14 0x16847509b <+1045>: add rax, rcx 0x16847509e <+1048>: add rax, qword ptr [rbp - 0x78] [1] 0x1684750a2 <+1052>: mov edi, dword ptr [rbp - 0x4c] 0x1684750a5 <+1055>: mov ecx, 0x0 0x1684750aa <+1060>: test r9d, r9d 0x1684750ad <+1063>: jle 0x1684750c1 ; <+1083> 0x1684750af <+1065>: mov bl, byte ptr [rdx + rcx]

``` Notice RAX is sign extended and contains a very large negative value. When the base of the buffer is added to it, [1], it is pointing well out of bounds, causing an out of bounds write. With proper calculation and set up this vulnerability could potentially be leveraged into a remote code execution vulnerability and give an attacker full control. The resulting crash is shown below.

``` RAX: 0xFFFFFE3196C5C21C RBX: 0x00000000DEDEDEAA RBP: 0x00007FFF5FBFA200 RSP: 0x00007FFF5FBFA120 o d I t s z a p c RDI: 0x00000000DEDEDE00 RSI: 0x0000000000000002 RDX: 0x0000000196C68D20 RCX: 0x0000000000000000 RIP: 0x00000001684750B2 R8: 0x0000000196C68D20 R9: 0x0000000000000002 R10: 0x00000000DEDEDEDE R11: 0x00000000DEDEDE00 R12: 0x0000000100000001 R13: 0x0000000000000002 R14: 0x0000000000000010 R15: 0x00000000DEDEDEDE

libOpenEXR.dylib`Imf_2_2::InputFile::readPixels: -> 0x1684750b2 <+1068>: mov byte ptr [rax + rcx], bl 0x1684750b5 <+1071>: add rcx, 0x1 0x1684750b9 <+1075>: cmp esi, ecx 0x1684750bb <+1077>: jne 0x1684750af ; <+1065> 0x1684750bd <+1079>: mov r15d, dword ptr [rbp - 0x30] 0x1684750c1 <+1083>: add rdx, r13 0x1684750c4 <+1086>: add rax, r14 0x1684750c7 <+1089>: add edi, r12d ```

CRASH INFORMATION

``` Crashed thread log = : Dispatch queue: com.apple.main-thread 0 libOpenEXR.dylib 0x00000001068b20b2 Imf_2_2::InputFile::readPixels(int, int) + 1068 1 libOpenEXR.dylib 0x000000010693c7d6 exrReadRGBFloat(char const, int, int, unsigned int, void*) + 621 2 com.apple.ImageIO.framework 0x00007fff8d3460cf copyImageBlockSetOpenEXR + 856 3 com.apple.ImageIO.framework 0x00007fff8d2f40f4 ImageProviderCopyImageBlockSetCallback + 651 4 com.apple.CoreGraphics 0x00007fff93f15cb4 CGImageProviderCopyImageBlockSetWithOptions + 132 5 com.apple.CoreGraphics 0x00007fff93f1739c CGImageProviderCopyImageBlockSet + 205 6 com.apple.CoreGraphics 0x00007fff93f4e7fd img_blocks_create + 517 7 com.apple.CoreGraphics 0x00007fff93f19c9f img_data_lock + 1788 8 com.apple.CoreGraphics 0x00007fff93f186c7 CGSImageDataLock + 151 9 libRIP.A.dylib 0x00007fff933ee1d4 ripc_AcquireImage + 972 10 libRIP.A.dylib 0x00007fff933ecc7e ripc_DrawImage + 1011 11 com.apple.CoreGraphics 0x00007fff93f17c48 CGContextDrawImageWithOptions + 571 12 com.apple.CoreGraphics 0x00007fff93f179f1 CGContextDrawImage + 51 13 com.apple.ImageIO.framework 0x00007fff8d31579e CGImageCreateCopyWithParametersNew + 2575 14 com.apple.ImageIO.framework 0x00007fff8d314b95 CGImageSourceCreateThumbnailAtIndex + 3821 15 com.apple.imageKit 0x00007fff8b1ce044 -[IKImageContentView _newCGImageFromImgSrc:index:displayProperties:imageScale:createBitmapImmediately:] + 747 16 com.apple.imageKit 0x00007fff8b1ce49c 69-[IKImageContentView setImageURL:imageAtIndex:withDisplayProperties:]_block_invoke + 57 17 com.apple.imageKit 0x00007fff8b1ce38b -[IKImageContentView setImageURL:imageAtIndex:withDisplayProperties:] + 799 18 com.apple.Preview 0x0000000101626162 0x10160b000 + 110946 19 com.apple.Preview 0x000000010161fe5d 0x10160b000 + 85597 20 com.apple.Preview 0x0000000101616b47 0x10160b000 + 47943 21 com.apple.AppKit 0x00007fff9978ea2b -[NSWindowController _windowDidLoad] + 592 22 com.apple.AppKit 0x00007fff9972b542 -[NSWindowController window] + 110 23 com.apple.Preview 0x0000000101614d9a 0x10160b000 + 40346 24 com.apple.AppKit 0x00007fff9991b03d -[NSWindowController showWindow:] + 36 25 com.apple.Preview 0x000000010161619e 0x10160b000 + 45470 26 com.apple.Foundation 0x00007fff97316f4e -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 1115 27 com.apple.Foundation 0x00007fff97316a75 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 131 28 com.apple.Preview 0x00000001016160df 0x10160b000 + 45279 29 com.apple.Preview 0x0000000101614f13 0x10160b000 + 40723 30 com.apple.Preview 0x00000001016ffdfe 0x10160b000 + 1003006 31 libdispatch.dylib 0x00007fff9c53693d _dispatch_call_block_and_release + 12 32 libdispatch.dylib 0x00007fff9c52b40b _dispatch_client_callout + 8 33 libdispatch.dylib 0x00007fff9c53ec1c _dispatch_main_queue_callback_4CF + 1685 34 com.apple.CoreFoundation 0x00007fff8e4a39e9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 9 35 com.apple.CoreFoundation 0x00007fff8e4628dd __CFRunLoopRun + 1949 36 com.apple.CoreFoundation 0x00007fff8e461ed8 CFRunLoopRunSpecific + 296 37 com.apple.HIToolbox 0x00007fff95160935 RunCurrentEventLoopInMode + 235 38 com.apple.HIToolbox 0x00007fff9516076f ReceiveNextEventCommon + 432 39 com.apple.HIToolbox 0x00007fff951605af _BlockUntilNextEventMatchingListInModeWithFilter + 71 40 com.apple.AppKit 0x00007fff9971aefa _DPSNextEvent + 1067 41 com.apple.AppKit 0x00007fff9971a32a -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454 42 com.apple.AppKit 0x00007fff9970ee84 -[NSApplication run] + 682 43 com.apple.AppKit 0x00007fff996d846c NSApplicationMain + 1176 44 libdyld.dylib 0x00007fff911725ad start + 1


exception=EXC_BAD_ACCESS:signal=11:is_exploitable=yes:instruction_disassembly=movb %bl,(%rax,%rcx):instruction_address=0x00000001068b20b2:access_type=write:access_address=0x00007e214703dc0c: Crash accessing invalid address. Consider running it again with libgmalloc(3) to see if the log changes. bootstrap_look_up: (os/kern) unknown error code (44e) + EXIT_VALUE=255 + exit 255 ```

TIMELINE

  • 2016-05-16 - Vendor Disclosure
  • 2016-07-18 - Public Release