CVE-2018-3858
An exploitable heap overflow exists in the TIFF parsing functionality of Canvas Draw version 4.0.0. A specially crafted TIFF image processed via the application can lead to an out-of-bounds write, overwriting arbitrary data. An attacker can deliver a TIFF image to trigger this vulnerability and gain the ability to execute code.
ACDSystems Canvas Draw 4.0.0
https://www.canvasgfx.com/en/products/canvas-draw
8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-122: Heap-Based Buffer Overflow
Canvas Draw 4 is a graphics editing tool used to create and edit images, as well as other graphic-related material. This product has a large user base, and is popular in its specific field. The vulnerable component is in the handling of TIFF images. TIFF is a raster-based image format used in graphics editing projects, thus making it a very common file format for such an application.
The vulnerability arises in the parsing of a tiled TIFF image with the PlanarConfiguration tag set. TIFF has two distinct ways for dealing with PlanarConfiguration, and by setting this tag to the default chunky version, i.e. stored contiguously with a tiled image, the application is thrown into a special parsing loop. Running the application with the vulnerable TIFF image and Guard Malloc, we get the crash below.
Process 43138 stopped
* thread #1: tid = 0x814c5, 0x0000000101f6cbe8 ImageGear18`IGRaster::PlanarPackedToStd(long long, long long, long long, long long, unsigned char const*, void*, long long) + 248, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x3d05d0000)
frame #0: 0x0000000101f6cbe8 ImageGear18`IGRaster::PlanarPackedToStd(long long, long long, long long, long long, unsigned char const*, void*, long long) + 248
ImageGear18`IGRaster::PlanarPackedToStd:
-> 0x101f6cbe8 <+248>: mov byte ptr [r10], r8b
0x101f6cbeb <+251>: add ecx, eax
0x101f6cbed <+253>: add r10, rdi
0x101f6cbf0 <+256>: dec r9
As can be seen above, the application is processing the planar packed information. If we look to where the buffer in R10 comes from, we can see the size being used for allocation. The malloc log for R10 is below.
ALLOC 0x3c704eff0-0x3c704eff7 [size=8]: TIF_read | _TIF_read | _TIF_Load_Uncompressed | _TIF_Load_Uncompressed_subs | AF_memm_alloc | malloc
And the area where this is calculated inside of _TIF_Load_Uncompressed_subs
.
call _IO_raster_size_get
mov [rbp+var_50], rax
mov r12d, eax
lea rdx, aApplicationsBu_178 ; "/Applications/buildAgent/work/90a7e357b"...
mov edi, r13d
mov rsi, r12
mov ecx, 1796h
call _AF_memm_alloc
The raster size of this image is returned, then passed into a malloc wrapper, returning a properly allocated buffer. The problem arises when using the buffer inside of PlanarPackedToStd
, the counter for the loop is miscalculated, and the overflow occurs. The relevant code is shown below.
mov eax, 8
mov r12,eax [0]
mov rax, r15 [1]
cqo
idiv r12
mov [rbp+var_30], rax [2]
The above code calculates the loop counter for how many planars to unpack. At [0], eight is set as the value used for the size of the planar. Then, R15 is directly passed in and is too large a value. This causes the loop counter to be written as four, and causes the buffer to be overflowed. Below is the use of the counter variable and the vulnerable buffer to cause the overflow.
do
{
...
do
{
*vuln_buffer = data & (mem >> data_calc);
vuln_buffer = &vuln_buffer[inc_1]; [1]
--v22;
++inc_1;
}
while ( v22 );
}
++count;
}
while ( count != vuln_counter ); [2]
At [1], the buffer is being accessed in the loop with the counter of proper size. Then, at [2], we see the problem with the counter show up, and the buffer is overwritten, causing a vulnerable condition to arise. An attacker could craft arbitrary data to overwrite with and gain code execution through this vulnerability.
Crashed thread log =
: Dispatch queue: com.apple.main-thread
0 ImageGear18 0x00000001089dfbe8 IGRaster::PlanarPackedToStd(long long, long long, long long, long long, unsigned char const*, void*, long long) + 248
1 ImageGear18 0x0000000108895690 iIG_IP_planar_raster_unpack + 21
2 ImageGear18 0x00000001089f462f _TIF_process_planar + 266
3 ImageGear18 0x00000001089f38cd _TIF_Load_Uncompressed_subs + 1909
4 ImageGear18 0x00000001089f46be _TIF_Load_Uncompressed + 94
5 ImageGear18 0x00000001089ef2b6 _TIF_read + 1235
6 ImageGear18 0x00000001089eed85 TIF_read + 261
7 ImageGear18 0x00000001088ebdfd GPb_fltrm_READ_call_param + 178
8 ImageGear18 0x00000001088ebd45 GPb_fltrm_READ_call + 21
9 ImageGear18 0x00000001088c2bbf iIG_load_FD_CB_ex + 411
10 ImageGear18 0x0000000108a343b6 IG_load_FD_CB_ex + 91
11 com.acdsystem.canvastool.ImageIO 0x000000016882bd12 CIGReadFile_CB_ext::readFile() + 836
12 com.acdsystem.canvastool.ImageIO 0x0000000168858633 ImageGearAcquireProc(short, AcquireRecord*, int*, short*) + 722
13 com.acdsystem.canvastool.ImageIO 0x0000000168858bf2 ImageIORunAcquireProc(_ImageIOAcquireState*) + 750
14 com.acdsystem.canvastool.ImageIO 0x000000016885678a 0x1687d8000 + 518026
15 com.acdsystem.canvastool.ImageIO 0x0000000168857ef4 DoImportFile(ImportFileMsg*) + 817
16 com.acdsystem.canvastool.ImageIO 0x000000016880b7c1 toolmain() + 917
17 com.acdsystem.canvastool.ImageIO 0x000000016883790a stdtool(TToolCallBlock*) + 122
18 com.acdsystem.canvastool.ImageIO 0x0000000168837889 cvtool_main(TToolCallBlock*) + 9
19 com.acdsystems.Canvas-Draw4 0x0000000106c275b0 0x106aee000 + 1283504
20 com.acdsystems.Canvas-Draw4 0x00000001076fcb76 0x106aee000 + 12643190
21 com.acdsystems.Canvas-Draw4 0x00000001076fc438 0x106aee000 + 12641336
22 com.acdsystems.Canvas-Draw4 0x000000010782c8a7 0x106aee000 + 13887655
23 com.apple.AppKit 0x00007fffafee4bd3 -[NSApplication _doOpenFile:ok:tryTemp:] + 322
24 com.apple.AppKit 0x00007fffafaa3ba7 -[NSApplication finishLaunching] + 1624
25 com.apple.AppKit 0x00007fffafaa3148 -[NSApplication run] + 267
26 com.apple.AppKit 0x00007fffafa6de0e NSApplicationMain + 1237
27 libdyld.dylib 0x00007fffc7734235 start + 1
log name is: ./crashlogs/f.crashlog.txt
---
exception=EXC_BAD_ACCESS:signal=11:is_exploitable=yes:instruction_disassembly=movb %r8b,(%r10):instruction_address=0x00000001089dfbe8:access_type=write:access_address=0x0000000385a3a000:
Crash accessing invalid address.
2018-03-20 - Vendor Disclosure
2018-04-18 - 30 day follow up
2018-04-19 - Vendor escalated to Canvas development team
2018-05-02 - 45 day follow up
2018-06-25 - Vendor confirmed fix scheduled for next update
2018-07-19 - Public Release
Discovered by Tyler Bohan of Cisco Talos.