An exploitable use-after-free vulnerability exists in the Length parsing function of NitroPDF. A specially crafted PDF can cause a type confusion, resulting in a use-after-free condition. An attacker can craft a malicious PDF to trigger this vulnerability.
7.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-416: Use After Free
NitroPDF is a popular PDF tool used to create and edit PDF files. NitroPDF has a wide array of features for automated PDF creation as well as reviewing differences between various PDFs.
The module tested for this advisory is below:
00007ffb`eb750000 00007ffb`ec559000 npdf (export symbols) npdf.dll Loaded symbol image file: npdf.dll Image path: C:\Program Files\Nitro\Pro\12\npdf.dll Image name: npdf.dll Browse all global symbols functions data Timestamp: Tue Mar 26 15:48:15 2019 (5C9A900F) CheckSum: 00D05033 ImageSize: 00E09000 File version: 220.127.116.112 Product version: 18.104.22.1682
One attribute PDFs to read a Length value of a field is /Length. This attribute expects a valid integer for its parameter. A simple example of this is shown below:
21 0 obj << /Filter /Flate /Length 17 >> stream endstream endobj
When parsed, this integer is converted to internal Integer object via CosIntegerValue.
npdf+0x352508 .text:0000000000352508 mov rcx, [rsp+0D8h+var_28] .text:0000000000352510 call ?CosIntegerValue@@YAHUOPAQUE_64_BITS@@@Z ; CosIntegerValue(OPAQUE_64_BITS) .text:0000000000352515 nop
This Integer object is then inserted into the document dictionary used for later reference. If the /Length value is instead a reference object, the parser continues to treat this value as a normal integer.
21 0 obj << /Filter /Flate /Length 17 0 R >> stream endstream endobj
When the parser attempts to use this reference object as an integer, the parser recognizes that the value is incorrect, and frees the object. This reference object is not removed from the document dictionary itself, causing a stale pointer to be left behind in the main dictionary.
This can be further shown in the trace of the proof of concept.
= Action = Size = Address = Flags = (+) TimeStart = (+) TimeEnd = Result = = [0x14966] - Alloc - 0x2040 - 0x1beac7f2fc0 - 0x0 - 1A72BD:5AF - 1A72DA:3E - = = [0x122e9] - Free - - 0x1beac7f2fc0 - 0x0 - 2FDA24:631 - 2FDA56:44 - 0x1 =
The address is freed at the 2FD124:631 time and further used at 37E328:0.
Time Travel Position: 37E328:0 npdf!CAPUnit::operator=+0x9ca: 00007ff9`897626da f6431004 test byte ptr [rbx+10h],4 ds:000001be`ac7f4680=02
This constitutes a use after free condition. By using other elements of the PDF document it would be possible to allocate a controlled object in place of the freed one before the stale pointer is reused which would result in further memory corruption and ultimately arbitrary code execution.
(84920.f7118): Access violation - code c0000005 (first/second chance not available) First chance exceptions are reported before any exception handling. This exception may be expected and handled. Time Travel Position: 37E328:0 npdf!CAPUnit::operator=+0x9ca: 00007ff9`897626da f6431004 test byte ptr [rbx+10h],4 ds:000001be`ac7f4680=02 !analyze -v BUCKET_ID_PREFIX_STR: APPLICATION_FAULT_INVALID_POINTER_READ_AFTER_CALL_AVRF_
2019-05-07 - Vendor disclosure
2019-07-02 - 60 day follow up
2019-07-29 - 2nd follow up (90 days approaching notice)
2019-08-06 - 3rd follow up
2019-08-07 - Vendor acknowledged & advised prior emails went to spam folder; Talos issued copy of report
2019-09-03 - Talos granted disclosure extension to 2019-09-10
2019-09-05 - Vendor advised issues will be addressed in a future release (timeline unknown)
2019-10-09 - Public Disclosure
Discovered by Cory Duplantis and Aleksandar Nikolic of Cisco Talos.