Talos Vulnerability Report

TALOS-2018-0552

ACD Systems Canvas Draw 4 IO Metadata Out-of-Bounds Write Code Execution Vulnerability

July 19, 2018
CVE Number

CVE-2018-3870

Summary

An exploitable out-of-bounds write exists in the PCX parsing functionality of Canvas Draw version 4.0.0. A specially crafted PCX image processed via the application can lead to an out-of-bounds write, overwriting arbitrary data. An attacker can deliver a PCX image to trigger this vulnerability and gain code execution.

Tested Versions

ACDSystems Canvas Draw 4.0.0

Product URLs

https://www.pl32.com/

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-787: Out-of-bounds Write

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 PCX images. PCX was a popular image format with early computers, and although it has been replaced by more sophisticated formats, it is still in use and is fully supported inside of Canvas Draw.

The vulnerability arises in the parsing of the PCX image, specifically dealing with the compression of the image. The compression scheme is determined via the file header, and by choosing run length encoding as the compression, the program writes out of bounds using user-controlled data. The problem lies in the error-checking in the code. If there is an error present, the code path can be altered and allows user-controlled data to be accessed without validation. The initial crash is below.

* thread #1: tid = 0xb02b8d, 0x0000000101f8623b ImageGear18`IO_metad_item_get + 90, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x0000000101f8623b ImageGear18`IO_metad_item_get + 90
ImageGear18`IO_metad_item_get:
->  0x101f8623b <+90>: jmp    rax
    0x101f8623d <+92>: add    rsp, 0x8
    0x101f86241 <+96>: pop    rbx
    0x101f86242 <+97>: pop    r12

rax = 0x00a7a7a700a6a6a6

Looking further into the assembly, we can see where the RAX value has been set:

__text:0000000101F861FE                 mov     r14, rdi                    [0]
...
__text:0000000101F86201                 call    _AF_error_check             [1]
__text:0000000101F86206                 test    rax, rax
__text:0000000101F86209                 jnz     short loc_101F8623D
__text:0000000101F8620B                 mov     rax, [r14+128h]             [2]

At [1], there is a call to error check to see if the everything is OK and if this fails, returns a non-zero status: RAX is loaded with the value from R14 [2]. At the function prologue [0], RDI gets loaded into the R14 register. Checking the calling function, we can see the error:

__text:0000000101ED8BDE                 mov     rdi, r13                   [3]
__text:0000000101ED8BE1                 mov     esi, 1Fh        
__text:0000000101ED8BE6                 mov     ecx, 1Fh        
__text:0000000101ED8BEB                 mov     r8d, 3          
__text:0000000101ED8BF1                 xor     r9d, r9d        
__text:0000000101ED8BF4                 call    _IO_metad_item_get           [4]

The R13 value at location [3], is user-controlled and not verified to contain the expected structure. Therefore, when calling into the meta data function [4] an exploitable condition arises. The user data is accessed as if it was a struct, and a function pointer is attempted to be called. This allows an attacker to leverage control and potentially gain code execution.

Crash Information

Crashed thread log = 
: Dispatch queue: com.apple.main-thread
0   ImageGear18                     0x000000010c0c523b IO_metad_item_get + 90
1   ImageGear18                     0x000000010c017063 PCX_header_read + 175
2   ???                             0x003737370b363636 0 + 15541833269917238

log name is: ./crashlogs/1.crashlog.txt
---
exception=EXC_BAD_ACCESS:signal=11:is_exploitable=yes:instruction_disassembly=jmp   *%eax:instruction_address=0x000000010c0c523b:access_type=exec:access_address=0x0000000000000000:
The exception code indicates that the access address was invalid in the 64-bit ABI (it was > 0x0000800000000000).

Timeline

2018-04-03 - Vendor Disclosure
2018-07-19 - Public Release

Credit

Discovered by Tyler Bohan of Cisco Talos.