Talos Vulnerability Report

TALOS-2018-0682

AutoDesk AutoCAD 2019 LinetypeTableRecord Code Execution Vulnerability

February 14, 2019
CVE Number

CVE-2019-7360

Summary

An exploitable use-after-free vulnerability exists in the DXF-parsing functionality of AutoDesk AutoCAD 2019. A specially crafted DXF file can cause a use-after-free vulnerability, resulting in code execution.

Tested Versions

AutoDesk AutoCAD 2019 P.46.0.0

Product URLs

https://www.autodesk.com/products/autocad/overview

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-416: Use After Free

Details

AutoDesk AutoCAD is a design and drafting application. AutoCAD helps civil engineers draft practically any civil engineering structure with ease, speed and accuracy.

One of the file formats AutoCAD supports is DXF (drawing exchange format). DXF was developed by AutoDesk to help pass data between the variety of AutoDesk applications. The format is a tagged data format where each data element is prepended with a number that represents a group code signifying how the data is interpreted.

The module used for analysis is shown below.

0:000> lm vm acdb23
start             end                 module name
00007ffd`bc550000 00007ffd`bda40000   acdb23     (export symbols)       C:\Program Files\Autodesk\AutoCAD 2019\acdb23.dll
	Loaded symbol image file: C:\Program Files\Autodesk\AutoCAD 2019\acdb23.dll
	Image path: C:\Program Files\Autodesk\AutoCAD 2019\acdb23.dll
	Image name: acdb23.dll
	Timestamp:        Mon Jan 29 20:32:20 2018 (5A6FF554)
	CheckSum:         014D5C2F
	ImageSize:        014F0000
	File version:     23.0.46.0
	Product version:  23.0.46.0

One element type handled by the DXF parser is the LinetypeTableRecord. In each LinetypeTableRecord, there are some number of Linetype Elements that make up each LinetypeTableRecord. In order to allocate enough space for a variable number of Elements, the LinetypeTableRecord must tell the parser how many Elements follow.

.text:00000000019187F6 188                 mov     eax, 50h ; 
.text:00000000019187FB 188                 mul     r14      ; [0]
.text:00000000019187FE 188                 mov     rcx, 0FFFFFFFFFFFFFFFFh
.text:0000000001918805 188                 cmovo   rax, rcx
.text:0000000001918809 188                 add     rax, 8
.text:000000000191880D 188                 cmovb   rax, rcx
.text:0000000001918811 188                 mov     rdx, rax
.text:0000000001918814 188                 xor     ecx, ecx
.text:0000000001918816 188                 call    cs:acHeapAlloc(void *,unsigned __int64)

The number of Elements is passed at [0] to a HeapAlloc call creating a memory region for the subsequent Elements. The memory region is then initialized with the subsequent items from the file [1] in the following snippet.

.text:000000000191881C 188                 mov     [rsp+180h+var_138], rax ; Newly created HeapAlloc
.text:0000000001918821 188                 xor     r8d, r8d
.text:0000000001918824 188                 test    rax, rax
.text:0000000001918827 188                 jz      short loc_1918855
.text:0000000001918829 188                 mov     [rax], r14
.text:000000000191882C 188                 lea     rbx, [rax+8]
.text:0000000001918830 188                 lea     rax, deallocate_linetype
.text:0000000001918837 188                 mov     [rsp+180h+a5], rax ; a5
.text:000000000191883C 188                 lea     r9, init_linetype ; [1]
.text:0000000001918843 188                 mov     r8, r14         ; a3
.text:0000000001918846 188                 mov     edx, 50h ; 'P'  ; a2
.text:000000000191884B 188                 mov     rcx, rbx        ; a1
.text:000000000191884E 188                 call    `eh vector constructor iterator'(void *,unsigned __int64,unsigned __int64,void (*)(void *),void (*)(void *))

After initialization, the current memory region is stored in offset 0x50 of the current LinetypeTableRecord [2].

.text:0000000001918855 188                 mov     rbx, r8
.text:0000000001918858 188                 mov     [rsi+50h], rbx ; [2]

Each new Element from the file goes through this same process. If there is already a memory region at offset 0x50, this region goes through a bit of processing before ultimately being deleted.

.text:00000000019187C2 188                 add     rcx, 0FFFFFFFFFFFFFFF8h
.text:00000000019187C6 188                 call    cs:operator delete(void near *)

This sequence of deletion and allocation occurs for each Element in the file. If the Linetype from the file claims to have no Elements, then the deletion sequence is executed, but the allocation section is not, since there is a check to determine if the number of Elements is greater than zero.

.text:00000000019187D8 188                 test    dx, dx
.text:00000000019187DB 188                 jz      continue_loop

During the destruction of this LinetypeTableRecord, this memory region at offset 0x50 is referenced and one of the vtable pointers is called [3] if the pointer is valid [4].

.text:000000000108B22F 028                 mov     rcx, [rcx+50h]
.text:000000000108B233 028                 test    rcx, rcx
.text:000000000108B236 028                 jnz     short loc_108B245
...
.text:000000000108B245 028                 cmp     qword ptr [rcx-8], 0 ; [4]
.text:000000000108B24A 028                 jz      loc_1218670
.text:000000000108B250 028                 mov     rax, [rcx]
.text:000000000108B253 028                 mov     edx, 3
.text:000000000108B258 028                 call    qword ptr [rax] ; [3]

Above, we can see that if a zero-length Element field is given, the region is deallocated without being reallocated. This produces a use-after-free vulnerability. If an attacker can control this memory region, then arbitrary code execution can be achieved via the calling of one of the vtable pointers.

Crash Information

rax=00007ffd7f407620 rbx=000001eb34eccf90 rcx=000001eb33a60eb8
rdx=0000000000000001 rsi=000001eb3b618f70 rdi=0000000000000001
rip=00007ffd7e7cb245 rsp=000000690dbfbdb0 rbp=000000690dbfbf09
r8=00007ffd7e7ca728  r9=000001eb4e22c1b0 r10=00007ffd7e7dfb54
r11=000001eb33261ec0 r12=00007ffd7e76b950 r13=00007ffd7e740000
r14=000001eb35c38fe0 r15=0000000000000000iopl=0         nv up ei pl nz na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
acdb23!AcDbLinetypeTableRecord::AcDbLinetypeTableRecord+0xac9:
00007ffd`7e7cb245 488379f800      cmp     qword ptr [rcx-8],0 ds:000001eb`33a60eb0=????????????????

Timeline

2018-10-01 - Vendor Disclosure
2019-02-14 - Public Release

Credit

Discovered by Cory Duplantis of Cisco Talos.