πŸ”’
There are new articles available, click to refresh the page.
Before yesterdayZero Day Initiative - Blog

ZDI-21-171: Getting Information Disclosure in Adobe Reader Through the ID Tag

18 February 2021 at 17:25

Sometimes the only thing between you and a successful exploit is an information leak. While I see my fair share of information disclosure bugs on the job, it’s not every day that I see one that is so clean and elegant. Then again, it’s not every day I get the privilege of looking at some of Β Mark Yason's stellar research. This blog covers one such information leak Mark submitted to the program and recently patched by Adobe.

Let’s talk aboutΒ  ZDI-21-171, but first, here’s a quick video showing the bug in action.

The Vulnerability

The issue exists due to the way Adobe Reader handles the ID tag within the PDF trailer. The problem is that when processing the array values for the ID tag, the application does not anticipate anything over 0x100 bytes.Β  With this knowledge and some JavaScript in hand, an attacker can leverage this to disclose the base address of Annots.api.

What exactly are we talking about?

If you pop open a PDF document in an editor, chances are that at the bottom, you’ll see a File Trailer that looks something like this:

Figure 1 - Example PDF Trailer

Figure 1 - Example PDF Trailer

According to Adobe’s documentation, the trailer consists of one or more key-value pairs.

Figure 2 - Adobe’s File Trailer documentation

Figure 2 - Adobe’s File Trailer documentation

The key-value pair of interest is ID, which is β€œan array of two strings constituting a file identifier for the file.” (See section 9.3, β€œFile Identifiers” in the document referenced above.) Our proof of concept is shown below and contains overly long array values:

Figure 3 - Proof of Concept PDF Trailer

Figure 3 - Proof of Concept PDF Trailer

What happens when the application encounters an ID key in a file trailer? During the parsing of the ID key, Reader will call a function that will return the size of the ID array values and uses that value to populate the following structure:

Figure 4 - Trailer ID Structure

Figure 4 - Trailer ID Structure

This is best illustrated by the following pseudocode:

Figure 5 - Pseudocode to retrieve File ID

Figure 5 - Pseudocode to retrieve File ID

The f_AcroDocGetFileID method returns the actual size of the file ID in the PDF even if the passed buffer argument is NULL and the buffer size argument is smaller than the actual size of the file ID. This value is then used to set the originalIDLen and modifiedIDLen properties without any check if the value is greater than 0x100 bytes.

Following this in the debugger, we can see that the parameters on the stack align with what we’re seeing in the debugger.

Figure 6 - A look at the stack and the returned value

Figure 6 - A look at the stack and the returned value

When the function returns, the structure looks like this:

Figure 7 - Returned stack structure

Figure 7 - Returned stack structure

Note the returned size in @eax. The issue here is that the return value was not checked to determine if it is greater than 0x100 before storing the value in this->originalIDLen and this->modifiedIDLen.

At this point, the structure is setup with invalid length values. This comes into play later with a call to Collab.documentToStream(), which invokes a memcpy call. This is shown below:

Figure 8 - This memcpy leads to an out-of-bounds read

Figure 8 - This memcpy leads to an out-of-bounds read

When the application tries to copy the originalID into a heap-based buffer, it uses the new 0x400 bytes size instead of the expected 0x100 bytes and allows a user to leak data from the stack. The result is a stack-based buffer out-of-bounds read can be leveraged to disclose the base address of Annots.api through the Collab.documentToStream() API call.

Figure 9 - Annots.api base address successfully leaked

Figure 9 - Annots.api base address successfully leaked

Wrapping up

Adobe Reader is a common target for attackers since the PDF format is so ubiquitous. While this blog covers an info disclosure bug, Adobe recently patched this along with other vulnerabilities that could allow remote code execution, including one bug that was being actively exploited. Getting code execution on modern applications typically requires multiple steps, and leaking memory addresses is often the first step towards a full exploit chain. Combine this bug with something that allows code execution and a sandbox escape, and you could have a full compromise. You should definitely apply the security patch to all affected systems as soon as possible.

You can find me on Twitter at @mrpowell and be sure to follow the team for the latest in exploit techniques and security patches.

ZDI-21-171: Getting Information Disclosure in Adobe Reader Through the ID Tag

  • There are no more articles
❌