CVE-2019-7360
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.
AutoDesk AutoCAD 2019 P.46.0.0
https://www.autodesk.com/products/autocad/overview
8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-416: Use After Free
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.
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=????????????????
2018-10-01 - Vendor Disclosure
2019-02-14 - Public Release
Discovered by Cory Duplantis of Cisco Talos.