CVE-2019-5042
An exploitable Use-After-Free vulnerability exists in the way FunctionType 0 PDF elements are processed in Aspose.PDF for C++. A specially crafted PDF can cause a dangling heap pointer, resulting in a use-after-free . An attacker can send a malicious PDF to trigger this vulnerability.
Aspose.PDF for C++ 19.2
https://products.aspose.com/pdf
8.8 - CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE-416: Use After Free
Aspose provides a series of APIs for manipulating or converting a large family of document formats. Aspose.PDF is a library used for editing, writing, and rendering PDFs. Aspose.PDF provides a number of different language bindings to allow modification or creation of PDFs from a number of different developer environments.
PDFs have a known huge feature set. One of these features are Function Objects. From the PDF v1.7 Specification, “PDF is not a programming language, and a PDF file is not a program. However, PDF does provide several types of function objects (PDF 1.2) that represent parameterized classes of functions, including mathematical formulas and sampled representations with arbitrary resolution. Functions are used in various ways in PDF, including device-dependent rasterization information for high-quality printing halftone spot functions and transfer functions), color transform functions for certain color spaces, and specification of colors as a function of position for smooth shadings.”
The module used for this research is described below:
00007ffb`55a80000 00007ffb`5adc6000 Aspose_PDF_vc141x64 C (export symbols) Aspose.PDF_vc141x64.dll
Loaded symbol image file: Aspose.PDF_vc141x64.dll
Image path: C:\Aspose.PDF_for_C++_19.2\example\x64\Release\Aspose.PDF_vc141x64.dll
Image name: Aspose.PDF_vc141x64.dll
Browse all global symbols functions data
Timestamp: Thu Feb 21 10:05:05 2019 (5C6ECC31)
CheckSum: 00000000
ImageSize: 05346000
A traditional example use case of a FunctionType looks like the following object:
12 0 obj
<<
/Length 64
/FunctionType 0
/Size [ 10 ]
/Decode [ 0 1 0 1 ]
/Range [ 0 255 0 255 ]
/BitsPerSample 8
/Domain [ 0 1 ]
>>
stream
...
endstream
endobj
While parsing a FunctionType, various heap objects are created. One such is an object of size 0x78 which is allocated and then immediately initialized.
Aspose.PDF_vc141x64.dll+0x1e4220d
crashing_obj = (CrashingObj *)malloc_wrapper(0x78);
if (crashing_obj == (CrashingObj *)0x0) {
// Failed to allocate
}
else {
crashing_obj->field_0x8 = 0x25640f8;
crashing_obj->field_0x70 = 0x2564108;
Object((Object *)&crashing_obj->field_0x38);
crashing_obj->field_0x68 = 0x2552f90;
*(undefined8 *)((longlong)&crashing_obj->field_0x70 + (longlong)*(int *)(crashing_obj->field_0x70 + 4)) = 0x2552fa0;
crashing_obj->field_0x0 = (CrashingObj *)0x25535a0;
// Further initialization
Below are all of the allocations and frees involving this object.
Action Address Size TimeStart Result
Alloc - 0x1e772ee0000 - 0x78 - 46E4BE:7B -
Free - 0x1e772ee0000 - - 47A6A2:47 - 0x1
Above we see the address being allocated at TimeStamp 46E4BE:7B
and being freed at 47A6A2:47
. Taking a look at the reads and writes of this particular object shows the various usages of the fields in the object. For example, we see the initial writing of uninitialized data with 0xc0c0c0c0c0c0c0c0 [0]. We can also further cross-reference the TimeStamps seeing that all memory access time stamps are within range of the allocation and freed timestamps.
EventType TimeStart AccessType RIP Address Size Value
===========================================================================================================================
- MemoryAccess - 46E4D9:22 - Write - 0x7ffbc31e2ff8 - 0x1e77f6def80 - 0x10 - 0xc0c0c0c0c0c0c0c0 [0]
- MemoryAccess - 46E4DB:4E - Write - 0x7ffb578c222a - 0x1e77f6def88 - 0x8 - 0x7ffb57fe40f8
- MemoryAccess - 46E4DB:64 - Write - 0x7ffb578c2269 - 0x1e77f6def80 - 0x8 - 0x7ffb57fd35a0
- MemoryAccess - 46E4DB:65 - Read - 0x7ffb578c226c - 0x1e77f6def88 - 0x8 - 0x7ffb57fe40f8
...
- MemoryAccess - 46E4DB:85 - Read - 0x7ffb578c2307 - 0x1e77f6def88 - 0x8 - 0x7ffb57fe40f8
- MemoryAccess - 46E4DB:91 - Read - 0x7ffb578c2339 - 0x1e77f6def88 - 0x8 - 0x7ffb57fe40f8
===========================================================================================================================
Looking at the time of the crash of the proof of concept shows that the Address being decremented is the heap address that was freed prior at 47A6A2:47
.
Time Travel Position: 1233615:0 // [1]
Aspose_PDF_vc141x64!System::Collections::Generic::Dictionary<System::String,System::String>::begin+0x8b:
00007ffb`55c4ed5b f00fc14110 lock xadd dword ptr [rcx+10h],eax ds:000001e7`7f6def88=57fe40f8
rax=00000000ffffffff rbx=000001e77f6f6fc0 rcx=000001e77f6def78
Seeing that the TimeStamp is past the time of the free [1], but seeing the address being decremented was the address in the prior free, shows that we have a danling pointer left after the free resulting in a Use-After-Free vulnerability.
By carefully controling allocations after the object is freed, and attacker can place arbitrary objects in it’s place which can lead to further memory corruption and can ultimately result in arbitrary code execution.
rax=00000000ffffffff rbx=000001e77f6f6fc0 rcx=000001e77f6def78
rdx=000001e772ee0000 rsi=000001e77f75cf60 rdi=000001e77f6f0fc0
rip=00007ffb55c4ed5b rsp=0000007b1e34eb40 rbp=0000000000000001
r8=0000000000000000 r9=0000000000000001 r10=00000000ffffffef
r11=0000007b1e34ead0 r12=0000000000000001 r13=0000000000000000
r14=0000000000000000 r15=000001e77bc50f00
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
Aspose_PDF_vc141x64!System::Collections::Generic::Dictionary<System::String,System::String>::begin+0x8b:
00007ffb`55c4ed5b f00fc14110 lock xadd dword ptr [rcx+10h],eax ds:000001e7`7f6def88=57fe40f8
!analyze -v
BUCKET_ID: APPLICATION_FAULT_INVALID_POINTER_WRITE_AVRF_Aspose_PDF_vc141x64!System::Collections::Generic::Dictionary_System::String,System::String_::begin+8b
FAILURE_EXCEPTION_CODE: c0000005
2019-04-17 - Vendor disclosure
2019-08-24 - Vendor acknowledged & advised issues under review
2019-09-16 - Vendor patched
2019-09-17 - Public release
Discovered by Cory Duplantis and Aleksandar Nikolic Cisco Talos.