Threat Intelligence

    Mimecast Discovers Use-After-Free Zero-Day Vulnerability in Adobe Reader  

    Adobe Acrobat Reader is a popular target for exploitation attempts; Mimecast Threat Research Labs has discovered a new zero-day vulnerability impacting annotations and comments in the application.

    by Gil Mansharov
    92BLOG_1.jpg

    Key Points

    • Mimecast Threat Research Labs discovered a Use-After-Free vulnerability in the latest version of Adobe Acrobat Reader. The vulnerability resides in the implementation and use of annotations in PDF documents.
    • While the vulnerability does not allow for code execution, if exploited by attackers, combined with additional techniques, the vulnerability could further aid in gaining control over affected systems.
    • The vulnerability has not impacted any organizations as of this writing.

    Adobe Acrobat Reader is one of the most popular PDF readers, and as such, it remains a target for potential exploitation attempts. 

    This article details how the Mimecast Threat Research Labs team and I began debugging a zero-day vulnerability encountered during an investigation into reproducing 1-day vulnerabilities in Adobe Acrobat Reader. 

    Anatomy of PDF Annotations in Adobe Reader

    Most modern document readers, including Adobe Acrobat Reader and Microsoft 365, implement features for annotations and comments.

    In Adobe Acrobat Reader, the functionality for annotations is implemented in a DLL file named Annots.api.

    During the course of our ongoing research, we decided to try to interact with the annotation feature using JavaScript for PDF. Luckily, Adobe documents the API for Acrobat’s Javascript engine (based on SpiderMonkey engine), highlighting that the following methods might be relevant:

    Method

    Description

    Doc.addAnnot

    Create an annotation in the document

    Doc.addField

    Create a field in the document

    Field.setAction

    Set an action for a given trigger for the field

    Annotation.destroy

    Destroy the annotation and remove it from the page

    Triggering a Crash

    While testing annotations with an outdated version of Adobe, we tested a script designed to trigger a crash for an existing 1-day vulnerability, and while debugging it, an unexpected crash was introduced. The basic script had the logic below.

    We created an annotation object:

    var annot = this.addAnnot({})

    Then added a text field to the annotation object:

    var f = annot.addField("some_name", {"cFieldType":"text"}, something, something)

    Finally, a trigger was set: the annotation object would be destroyed when the text field blurred.

    f.setAction("OnBlur", "annot.destroy()")

    When the annotation object was accessed programmatically, no unusual behavior was documented.

    However, clicking the text field demonstrated that somehow Adobe Acrobat Reader could access the annotation object, therefore triggering a Use-After-Free bug and crashing the application.

    We were seeing a classic Use-After-Free bug:

    • Free: The annotation object is being freed on an OnBlur event on the text field.

    f.setAction(“OnBlur”, “annot.destroy()”)

    • Use: Clicking the annotation after clicking the text field triggered the OnBlur event and freed the UI object of the annotation, but at the same time, the UI object of the Annotation was being accessed by clicking it.

    Technical Analysis

    To verify the root cause of the crash (Use-After-Free), we debugged Acrobat Reader with WinDBG, and activated GFlags to troubleshoot the bug. To ease the task of debugging, we were forced to disable Protected Mode in Adobe Acrobat Reader.

    When debugging the POC file to trigger the vulnerability, there was an access violation exception, as expected, due to access given to previously freed memory.

    With a simple heap spray in our Javascript code, we also managed to gain control over EIP by corrupting a function pointer in one of Acrobat Reader’s internal objects, as seen in Figure 1:

    Figure 1: Debugging and exception details in WinDBG

    In our Javascript code, we sprayed the heap with 0x0c0d bytes, and it modified the value of the ESI register.

    In addition, the EIP register pointed to the address 0x0, and we could see that the root cause of it was because of a call to a function located at ESI+0x20.

    The value at the address ESI+0x20 was 0x0, which meant that the instruction pointer would be set to this value, and because we had control over ESI, we could also control the function address to be called.

    Gaining control over EIP was not enough for successful exploitation, as in such scenarios the team needed to bypass additional mitigations such as ASLR, DEP, and Acrobat Reader’s sandbox.

    Diving Deeper

    When analyzing and potentially exploiting heap vulnerabilities, it’s important to understand the internals of the heap, and how the objects that we can corrupt are structured.

    Understanding the internal objects of Acrobat Reader isn’t that easy, as the program has no published symbols (unlike Microsoft Office), and it requires additional reverse engineering.

    After initial analysis of the vulnerability and the root cause of the vulnerability, the we decided to dive deeper.

    For this task, we looked at two modules we thought were the most relevant for this vulnerability: Annots.api and AcroRd32.dll.

    To make the analysis easier, we used WinDBG Preview and ran our POC file with Gflags and Time Travel Debugging enabled.

    This way, we could capture a trace file of the execution and replay it backwards and forwards with the debugger.

    We set a breakpoint at the first access we saw to the corrupted object, and when we reached the breakpoint, we wanted to see details on the corrupted heap chunk.

    The screenshot below shows how we could see that the call to the function at 0x710e7b70 changed the contents of the buffer pointed by EDI, and demonstrates how we saw that this was our corrupted buffer.

    Examining the heap chunk that pointed by EDI+0x7A, we could see that the chunk entry was at 0xb7c8010.

    Now we wanted to set a hardware breakpoint on this address, rewind the execution (using Time Travel Debugging), and check all the accesses to this address, including freeing and allocating memory in this address.

    Figure 2: First access to the corrupted object by our POC.

    After we rewound the execution and debugged the trace file with the breakpoints we set, we examined all the accesses to the address of the corrupted heap chunk entry.

    We wanted to have better understanding of the free heap chunk that was being used, which object it represented, the size of the object, and (preferably) its properties.

    After we examined the accesses to the freed heap chunk and filtered the ones that related to memory allocations/free, we could see the user’s allocation size of the chunk in the call to RtlAllocateHeap with the argument of 0x2D0 as the size.

    Figure 3: Object allocation with user size of 0x2D0 

    So, at this point, we knew that the program allocated 0x2D0 bytes for the corrupted object, if we ignored the additional 0x18 bytes allocated by the heap manager.

    As a reminder, the object was allocated by using the following Javascript code:

    var annot = this.addAnnot({})

    As we now had the call stack of the allocation, we were able to see where the object was being constructed by Acrobat Reader.

    When we took a look at the code at address AcroRd32!AIDE::PixelPartInfo::operator=+0x4e697f, we could see the allocated buffer and the buffer size, and we also could see a call to a function (create_CommentContainerView_object_internal) that constructed the object itself with initial values. 

    Figure 4: Construction of the object in AcroRd32!AIDE::PixelPartInfo::operator=+0x4e697f 

    Once we knew how the object was being constructed, we could see that we freed it with the action that we set in the OnBlur event using the following Javascript code:

    f.setAction("OnBlur", "annot.destroy()")

    By checking the call stack during the free operation of the object, we could also see that it was being freed by calling the destroy() API in the Annots.api library: 

    Figure 5: Call stack when freeing the object with the destroy() API 

    In the call stack, we could see the execution of code in the address Annots!PlugInMain+0xabadf was called from the EScript module (Acrobat Reader Javascript engine).

    Just by looking at the “destroy" string in the function, we discovered that the chunk had been freed by calling the destroy() API.

    Figure 6: Code at Annots!PlugInMain+0xabadf 

    Now that we knew that the object had been freed, we could see that we managed to take control over the free object by using generic Javascript functions for memory allocations (like creation of ArrayBuffer and DataView objects): 

    Figure 7: Corruption of the free object by heap spraying with Javascript 

    We could also see that the call stack in this scenario was different from the call stack that we saw in the this.addAnnot API call, and in this call stack, the allocation came from the EScript module of Acrobat Reader (the Javascript engine), and not from the Annots module as before.

    To gain code execution using the vulnerability, we only needed to bypass security mitigations such as DEP, ASLR, Acrobat Sandbox and more.

    Bypassing these mitigations required, in most cases, finding more vulnerabilities and chaining them together.

    Disclosure Timeline for CVE-2022-38437

    The vulnerability has been disclosed to Adobe through the HackerOne service.

    • August 24 – The vulnerability was disclosed to Adobe through the HackerOne service
    • August 25 – HackerOne analysts successfully reproduced the vulnerability and forwarded it to Adobe
    • October 14 – Adobe patched the vulnerability and assigned it CVE-2022-38437

    The Bottom Line

    In this research, our goal was to reproduce 1-day vulnerabilities in Acrobat Reader in order to understand it better and find potential fuzzing targets, but eventually we ended up finding a zero-day vulnerability that we probably couldn’t reach with fuzzing, as it requires specific user interaction with Acrobat Reader’s GUI with combination of Javascript. This vulnerability could further aid attackers in gaining control of affected systems. It is our hope that discovering and sharing our research on this vulnerability will help prevent that from happening.

     

    Subscribe to Cyber Resilience Insights for more articles like these

    Get all the latest news and cybersecurity industry analysis delivered right to your inbox

    Sign up successful

    Thank you for signing up to receive updates from our blog

    We will be in touch!

    Back to Top