Talos Vulnerability Report

TALOS-2018-0542

ACD Systems Canvas Draw 4 PlanarConfiguration Heap Overflow Code Execution Vulnerability

July 19, 2018
CVE Number

CVE-2018-3858

Summary

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.

Tested Versions

ACDSystems Canvas Draw 4.0.0

Product URLs

https://www.canvasgfx.com/en/products/canvas-draw

CVSSv3 Score

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

CWE

CWE-122: Heap-Based Buffer Overflow

Details

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.

Crash Information

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. 

Timeline

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

Credit

Discovered by Tyler Bohan of Cisco Talos.