CVE-2017-2812
A code execution vulnerability exists in the kdu_buffered_expand function of the Kakadu SDK 7.9. A specially crafted JPEG 2000 file can be read by the program and can lead to an out of bounds write causing an exploitable condition to arise.
Kakadu SDK 7.9 - OSX & Linux
8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-131: Incorrect Calculation of Buffer Size
Kakadu SDK is a commercial solution for the parsing and handling of JPEG 2000 images. This software is used by many high profile companies in the handling of JPEG 2000 images, including Apple. This vulnerability could have a large impact due to the number of users using this SDK to handle their images.
The JPEG 2000 format begins with a header describing the data that will be presented in the rest of the file. The header is parsed by scanning through, finding a marker, and parsing the data based off of the type of marker. The size of the current markers data is presented immediately following the marker itself. The vulnerability arises when the parser gets to the contiguous codestream section of the Jpeg2000 image. The codestream size is not checked and is overly large leading to excessive parsing of data erroneously. An outline of the vulnerable image is shown below.
<contiguousCodestreamBox>
<siz>
<lsiz>44</lsiz>
<rsiz>ISO/IEC 15444-1</rsiz>
<xsiz>268435456</xsiz>
<ysiz>32</ysiz>
<xOsiz>0</xOsiz>
<yOsiz>0</yOsiz>
<xTsiz>10879008</xTsiz>
</siz>
As can be seen the size parameters are overly large for a file of only 100 bytes. The program then goes into a loop using these sizes and allocates working buffers based off of the data these sizes point to.
do
{
data_value = *dataStruct; [1]
size = v160[v86] * data_value << (v186 ^ 1); [2]
new_size = size + 31;
v90 = operator new[](new_size);
The vulnerability arises in the fact that after multiple iterations of the loop the data_value
being read at [1], is zero thus the size calculation is zero at [2], and the buffer being allocated is of size 31 rather than the necessary size. When this buffer is used again for calculations it access beyond the bounds of the buffer and into memory in various places including potential calls and writes leading to a highly exploitable condition. Using a safe malloc implementation the crash is shown below.
* thread #1: tid = 0x2ca8ece, 0x000000010001209a kdu_buffered_expand`kd_supp_simd::avx2_int16_to_uint8_rs_ilv1(unsigned char*, short**, int,
int, int, bool, bool, int) + 191,
queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x100e99000)
frame #0: 0x000000010001209a kdu_buffered_expand`kd_supp_simd::avx2_int16_to_uint8_rs_ilv1(unsigned char*, short**, int, int, int, bool, bool,
int) + 191
kdu_buffered_expand`kd_supp_simd::avx2_int16_to_uint8_rs_ilv1:
-> 0x10001209a <+191>: vmovdqu ymmword ptr [rdi + 0x20], ymm3
0x10001209f <+196>: add ebx, -0x40
0x1000120a2 <+199>: sub rsi, -0x80
0x1000120a6 <+203>: add rdi, 0x40
Crashed thread log =
: Dispatch queue: com.apple.main-thread
0 kdu_buffered_expand 0x000000010d19309a kd_supp_simd::avx2_int16_to_uint8_rs_ilv1(unsigned char*, short**, int, int, int, bool, bool, int)
+ 191
1 kdu_buffered_expand 0x000000010d1873c2 kd_supp_local::kdsd_tile::process(kdu_core::kdu_thread_env*) + 456
2 kdu_buffered_expand 0x000000010d1898ef kdu_supp::kdu_stripe_decompressor::pull_common(int) + 429
3 kdu_buffered_expand 0x000000010d18420c main + 8721
4 libdyld.dylib 0x00007fff8c2d65ad start + 1
---
exception=EXC_BAD_ACCESS:signal=11:is_exploitable=yes:instruction_disassembly=.byte 0xc5 #bad opcode:instruction_address=0x000000010d19309a:access_type=unknown:access_address=0x000000010df1f000:
Crash accessing invalid address.
2017-04-18 - Vendor Disclosure
2017-08-04 - Public Release
Discovered by Aleksandar Nikolic and Tyler Bohan of Cisco Talos.