Talos Vulnerability Report

TALOS-2016-0103

Oracle OIT IX SDK TIFF ExtraSamples Code Execution Vulnerabiity

July 19, 2016
CVE Number

CVE-2016-3581

Description

While parsing a specially crafted TIFF file, a parser confussion can lead to a heap buffer overflow resulting in out of bounds memory overwrite leading to arbitrary code execution.

Tested Versions

Oracle Outside In IX sdk 8.5.1

Product URLs

http://www.oracle.com/technetwork/middleware/content-management/oit-all-085236.html

Details

While parsing a specially crafted TIFF file with ExtraSamples tag present, a parser confusion can lead to insuficient heap memory allocation which later results in a buffer overflow corrupting the heap structures which can be abused to achieve arbitrary code execution. As per the file format documentation ExtraSamples influences how many actual bits per sample there are in the file.

Size of the allocation is based directly on on ImageWidth value (at offset 0x6c in the supplied testcase) and is the allocation happens in the following basic block in libvs_tiff.so (image base is 0xB74E1000):

`
.text:B74F3DE4 mov     edx, [esp+11Ch+var_A8]
.text:B74F3DE8 mov     eax, [edx+30h]
.text:B74F3DEB mov     [ebp+4A8h], eax
.text:B74F3DF1 mov     eax, [edx+30h] 		[1]
.text:B74F3DF4 mov     [esp+11Ch+s], eax
.text:B74F3DF7 call    _SYSNativeAlloc
`

At [1], the size of the allocation is read from a structure on the heap which comes from the file directly. In the supplied testcase (minimal.tiff) this will be 0x20 bytes, resulting in 0x28 byte chunk being allocated.

The overflow happens in the following code in libvs_tiff6.so:

`
.text:B74EC5A8                 add     eax, [esp+26Ch+var_188]
.text:B74EC5AF                 movzx   eax, byte ptr [eax+esi] 			[1]
.text:B74EC5B3                 mov     edx, [esp+26Ch+var_250]
.text:B74EC5B7                 mov     [edx+ecx], al 					[2]
.text:B74EC5BA
.text:B74EC5BA loc_B74EC5BA:                           ; CODE XREF: VwStreamRead+9F6j
.text:B74EC5BA                 mov     ecx, [esp+26Ch+var_220]
.text:B74EC5BE                 movzx   eax, word ptr [ecx+0D8h]
.text:B74EC5C5                 add     esi, eax 						[3]
.text:B74EC5C7                 cmp     [ecx+3CCh], esi 					[4]
.text:B74EC5CD                 jbe     loc_B74EC09B
`

In the above code, at [1] a byte value is read from the heap and is written to a destination buffer at [2]. At [2], edx points at the begining of the previously allocated buffer (as discussed above) and ecx serves as offset, incremented by 1 in each iteration of the loop. This block of code is executed in a bigger loop, the rest of which is ommited for brevity. At [3], esi, which is a loop counter (also an index into a buffer at [1]), is incremented by value in eax which comes directly from SamplesPerPixel value in the file (2 in the supplied minimal.tiff). Finally, at [4], the esi counter is compared to a max value in ecx+0x3CC.

If the maximum value of the counter (ecx+0x3cc at [4] above) is greater than the allocated buffer a heap overflow can occur. Upper bound of this loop is calcualted in the following basic block:

`
.text:B74E8AEF loc_B74E8AEF:
.text:B74E8AEF mov     ecx, [esp+8Ch+arg_4]
.text:B74E8AF6 movzx   eax, word ptr [ecx+60h] 	[1]
.text:B74E8AFA imul    eax, [ecx+30h]           [2]
.text:B74E8AFE movzx   edx, word ptr [ecx+0D8h] [3]
.text:B74E8B05 imul    eax, edx                 [4]
.text:B74E8B08 add     eax, 7					[5]
.text:B74E8B0B shr     eax, 3 					[6]
.text:B74E8B0E mov     [ecx+3CCh], eax 			[7]
.text:B74E8B14 cmp     word ptr [ecx+0F8h], 0
.text:B74E8B1C jnz     loc_B74
`

At [1], the initial value is comes from BitsPerSample value from the file and is multiplied by a value coming from ImageWidth at [2]. At [3], a SamplesPerPixel value is retrieved and is multiplied with previous result at [4]. After 7 is added at [5], the final value is divided by 8 at [6]. The final value is written into heap structure pointed to by ecx at offset 0x3CC at [7].

In short, the upper bound for the loop in which the overflow happens is:

`
max = (( BitsPerSample * ImageWidth * SamplesPerPixel ) + 7) >> 3
`

In the supplied testcase, the upper bound for the loop is 0x80, and since increment in each iteration is 2 this leads to a buffer overflow of 0x40 bytes where only 0x28 were allocated, leading to an application crash.

In summary, both the size of the allocation and size of the overwrite are under direct control. The supplied testcase PoC.tiff demonstrates a more controled buffer overwrite where adjecent heap chunks are overwriten with ASCII A’s resulting in the following crash:

`
Breakpoint 4, 0xb74ec5ba in VwStreamRead () from /home/ea/oit_office/sdk/demo/libvs_tif6.so
edx            0x80d8920	135104800
ecx            0x0	0
esi            0x0	0
al             0x4b	75
Quit
(gdb) disable
(gdb) c
Continuing.
Export successful: 1 output file(s) created.
*** Error in `/home/ea/oit_office/sdk/demo/ixsample': double free or corruption (out): 0x080d8948 ***
======= Backtrace: =========
/usr/lib/libc.so.6(+0x6ce09)[0xb7e20e09]
/usr/lib/libc.so.6(+0x74406)[0xb7e28406]
/usr/lib/libc.so.6(cfree+0x56)[0xb7e2c676]
/home/ea/oit_office/sdk/demo/libwv_core.so(SYSNativeFree+0x1f)[0xb7a507e7]
...
Program received signal SIGABRT, Aborted.
0xb7fdbbc0 in __kernel_vsyscall ()
(gdb) x/x 0x80d8920
0x80d8920:	0xaaaa41aa
(gdb) x/x 0x80d8920-4
0x80d891c:	0x00000029      <- size of the overflown buffer
(gdb) x/x 0x080d8948
0x80d8948:	0x41414141
(gdb) x/x 0x080d8948-4
0x80d8944:	0x41414141      <- size corrupted
(gdb)
`

Breakpoint 4 is placed in the loop where the overwrite happens and here shows the initial values. The pointer to the allocated memory is 0x80d8920. After the crash, by examining the memory around it, we can see that the adjecent heap chunk has been overwriten.

The essential difference between the original TIFF file and the supplied minimal testcase is that the minimal testcase contains the ExtraSamples tag, which influences the calculations, as well as the different values for both BitsPerSample and SamplesPerPixel values.

This issue can be triggered by running the supplied testcase in the ixsample application supplied with the SDK.

Timeline

2016-04-12 - Vendor Notification
2016-07-19 – Public Disclosure

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.