Trustwave SpiderLabs Uncovers Unique Cybersecurity Risks in Today's Tech Landscape. Learn More

Trustwave SpiderLabs Uncovers Unique Cybersecurity Risks in Today's Tech Landscape. Learn More

Services
Capture
Managed Detection & Response

Eliminate active threats with 24/7 threat detection, investigation, and response.

twi-managed-portal-color
Co-Managed SOC (SIEM)

Maximize your SIEM investment, stop alert fatigue, and enhance your team with hybrid security operations support.

twi-briefcase-color-svg
Advisory & Diagnostics

Advance your cybersecurity program and get expert guidance where you need it most.

tw-laptop-data
Penetration Testing

Test your physical locations and IT infrastructure to shore up weaknesses before exploitation.

twi-database-color-svg
Database Security

Prevent unauthorized access and exceed compliance requirements.

twi-email-color-svg
Email Security

Stop email threats others miss and secure your organization against the #1 ransomware attack vector.

tw-officer
Digital Forensics & Incident Response

Prepare for the inevitable with 24/7 global breach response in-region and available on-site.

tw-network
Firewall & Technology Management

Mitigate risk of a cyberattack with 24/7 incident and health monitoring and the latest threat intelligence.

Solutions
BY TOPIC
Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
About Us
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Security Operations Platform
Trustwave Security Colony
Partners
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats
SpiderLabs Blog

Deep Analysis of CVE-2014-0502 – A Double Free Story

A lot has already been said about CVE-2014-0502, the Adobe Flash Player zero-day that was part of a targeted attack that infected several nonprofit organizations' websites. Several interesting aspects of the exploit were covered in various blog posts; including its use of a .gif image file containing shellcode, OS language and version checking for custom ROP gadgets, etc.

After spending quite some time investigating the file ourselves, we felt that the vulnerability was in itself very interesting and a thorough analysis of it would be interesting to share. Today we finally found some time to write it all up, so here it goes!

The vulnerability is a double-free vulnerability caused by a bug in how shared objects are handled by Adobe Flash Player. The following piece of code is responsible for triggering the vulnerability:

12317_e5308389-2901-4398-98cc-858cfc0876ec

What are Workers in flash?

Not too long ago Adobe added support for background threads, which are represented in ActionScript as "Workers." The purpose of a worker is to give the developer the possibility of running simultaneous tasks without freezing the Flash application. In simple words, this is an abstraction layer to support multi-threading within Flash.

What is a Shared Object?

Adobe's documentation includes the following details about shared objects:

[1] "A local shared object, sometimes called a "Flash cookie," is a data file that can be created on your computer by the sites you visit. Shared objects are most often used to enhance your web-browsing experience. For example, by allowing you to personalize the look of a website that you frequently visit." (Adobe)

[2] "When an application closes, shared objects are flushed, or written to a disk. You can also call the flush() method to explicitly write data to a disk." (Adobe)

Shared Objects give the ability to save offline data generated by the application. This data will remain available the next time the user loads the application.

What Actually Happens?

During the termination of a worker (Adobe Flash Player instance), all shared objects are (obviously) destroyed, but the shared object's data is flushed to the disk immediately before the objects are destroyed. The destructor procedure of a shared object first calls an "Exit" function that performs two important checks:

  1. Check for the "Pending Flush" flag – which indicates whether or not there is data that needs to be flushed to disk. In our sample the ActionScript code sobj.data.log='data…' turns the "Pending Flush" flag on.
  2. Check the domain's "Maximum Storage" settings (if not explicitly set for the hosting domain, this will be 100KB by default).

If the first check passes and the process tries to flush the data (to the path %appdata%\ Macromedia\Flash Player\#SharedObjects on disk), it frees the object block when finished whether it succeeds or not. Just before it proceeds to the freeing part, Adobe Flash Player performs garbage collection and decides that the "record" shared object is no longer in use (due to the fact that other related objects were freed.) It therefore starts another free operation whilst the first free operation is still in process, once again the "Exit" function (responsible for flushing) is executed. The first check is passed again since the "Pending Flush" flag is still on and the code attempts to flush the file to disk. This operation fails, since we exceed the 100KB per domain limit. Due to this failure the "Exit" function finishes without clearing the "Pending Flush" flag. Next, still in the inner free operation, the heap block that stored our "record" shared object is freed resulting in a double free.

Deeper Analysis

Here you can see the stack trace of the crash reproduced in our lab environment:

9893_710ea9de-7489-4c01-9ac9-c2438afb554b

From the crash we can figure out that the EAX register is supposed to point to the freed object's vftable(virtual functions table) and call the function at offset 0x8. By looking at this code in IDAPro we can see that the ESI register holds a reference to the freed object itself.

8860_3de72c62-2c92-4167-8f92-ec1d4aa69b9b

After adapting the sample (the ROP part) to lead the execution to the 0xCCCCCCC address and setting a breakpoint at the crash: bp Flash32_12_0_0_44+0x102f4b, we ran the modified sample.

We noticed that we hit our breakpoint a couple of times before it crashes, in particular (as shown in the screenshot below) the exact same object – the "record" object we created in ActionScript (as a result of the line SharedObject.getLocal("record")) is used first to executes a function from its vftable in a legitimate way. Following that, the player crashes for attempting to execute the same instruction when the object was already freed.

The screenshot below shows both hits of our breakpoint. The ESI register is pointing to the same object ("record") in both cases. You can clearly see that on the second hit the object has already been freed:

10378_85eedcb0-b20f-4054-beac-aa60a2b88c71

Ok so now we know which object was freed, but what caused it?

In order to understand what caused the bug, let's have another look at Adobe's documentation for shared objects:

"Whenan application closes, shared objectsare flushed, or written to a disk. You can also call the flush() method to explicitly write data to a disk." (Adobe)

This means that a shared object will basically try to flush data to the disk only when the shared object is destroyed, unless you explicitly use the flush() method.

After analyzing the functions from the crash call stack, we noticed that the crash was a result of the "record" shared object's destructor code, which was triggered by the termination of the worker. This means that before freeing the object the destructor calls a function that will eventually cause a crash (here we can assume that this function is somehow related to flushing the shared object before it is destroyed).

With that in mind, let's have a look at the function before our program crashed:

7784_088368bb-d0ec-4cec-a838-e1b3014abc19

The diagram above shows that this "flushing" function will not proceed unless the "record" object has a "Pending Flush" flag up (offset 0xc1).

In this sample, the "record" object has data pending to be flushed so this flag will be up upon reaching the code in the diagram above. Just after the first check of the flag, Adobe Flash Player will perform garbage collection and determine that the "record" shared object is no longer in use (as described above). This causes an additional call to the destructor of the "record" object from within the current destructor. This flow explains why the breakpoint discussed earlier is hit twice.

At this point the destruction process continues and attempts to flush the data to disk as well as clear the "Pending Flush" flag. This attempt fails because the data exceeds the maximum allowed size for this domain (100KB by default), and therefore the flag stays up. Once the inner destructor finishes the failed flushing attempt it will free the "record" object but leave the "Pending Flush" flag up.

The following screenshot shows the double free flow caused by the inner destructor:

10442_897e30a3-a14a-4671-a1a8-c3199ad505a6

This specific flow will result in the "Pending Flush" flag being up when the object was already freed, and therefore Adobe Flash Player will try to execute a function from a dereferenced pointer otherwise known as remote code execution.

An attacker can easily create a specially crafted flash file and use this vulnerability to control the execution flow and deliver a payload of their choice.

We hope that you enjoyed this analysis, and that you could follow the described flow even though the lack of symbols makes the analysis a bit more complex.

As always, remember to keep your Adobe Flash Player up-to-date in order to protect yourself.

Latest SpiderLabs Blogs

Zero Trust Essentials

This is Part 5 in my ongoing project to cover 30 cybersecurity topics in 30 weekly blog posts. The full series can be found here.

Read More

Why We Should Probably Stop Visually Verifying Checksums

Hello there! Thanks for stopping by. Let me get straight into it and start things off with what a checksum is to be inclusive of all audiences here, from Wikipedia [1]:

Read More

Agent Tesla's New Ride: The Rise of a Novel Loader

Malware loaders, critical for deploying malware, enable threat actors to deliver and execute malicious payloads, facilitating criminal activities like data theft and ransomware. Utilizing advanced...

Read More