Talos Vulnerability Report

TALOS-2019-0778

May 14, 2019

CVE Number

CVE-2019-7761

Summary

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.

Tested Versions

Adobe Acrobat Reader DC 2019.010.20069

Product URLs

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-416: Use After Free

Details

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:

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):

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.

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:

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.