Our analysis of the Adobe Flash zero-day vulnerability used in the latest Pawn Storm campaign reveals that the previous mitigation techniques introduced by Adobe were not enough to secure the platform.
Used in Pawn Storm to target certain foreign affairs ministries, the vulnerability identified as CVE-2015-7645 represents a significant change in tactics from previous exploits. It is important to note that Adobe has released the bulletin APSB15-27 to address this vulnerability; the latest version of Flash (22.214.171.124) is no longer vulnerable.
Some background knowledge
Adobe introduced several mitigation techniques for Flash exploits earlier this year, co-working with Google Project Zero. These mitigation techniques focused on reducing Vector.<*> exploits, because a corrupted Vector.<*> was frequently used to achieve the ability to read and write arbitrary parts of memory. This allows various security techniques like DEP/ASLR/CFG/EMET to be bypassed and achieve Remote Code Execution (RCE) within the browser process.
Once these mitigations were put in place, the exploits in the wild decreased, but they did not completely disappear. This latest vulnerability is the first zero-day exploit discovered in the wild after these mitigations were added.
How CVE-2015-7645 was used in Pawn Storm
As we’ve previously reported, Pawn Storm used this zero-day exploit to target many foreign affairs ministries from all over the globe. The targets were sent spear-phishing emails that contained URLs leading to the exploit. The emails (especially the email subjects and URL strings) were crafted to suggest that they were regarding news articles pertaining to recent events.
The exploit is downloaded when the victim clicks on the URL in the email. The exploit, which we detect as SWF_OLOLO.A, then drops a DLL file (“marlou.fel” ) detected as TROJ_SEDNIT.D. TROJ_SEDNIT.D then drops another DLL file (“mgswizap.dll”) which is detected as TSPY_SEDNIT.D. SEDNIT variants are known to be the malware used in all Pawn Storm campaigns.
Analyzing the Vulnerability’s Root Cause
This particular vulnerability is of a new type, which we can call Method Confusion. It is the most interesting Flash vulnerability I have ever analyzed.
The exploit SWF sample was obfuscated. After de-obfuscation and analysis, I found that the bug is located in the writeObject method of the ByteArray object. When processing ba.writeObject(some_obj), if some_obj is an object of a class which implements flash.utils.IExternalizable interface, it will call the writeExternal method of IExternalizable.
The writeExternal method must be implemented in the some_obj class’s definition. However, if there is a property field also named writeExternal and defined in an unusual way, the property writeExternal will hide the method writeExternal.
The tricky definition can be something like in the image below:
Figure 1. Custom class definition
After the writeExternal method is hidden by the writeExternal property, it will cause the method’s binding_id to have the wrong value. In ba.writeObject(some_obj), it needs to get the writeExternal’s function binding_id first. It will then use this to get the method’s environment structure using a sentence such as methods[binding_id].
After getting the method environment, it can be JITed to native code, which is then called.
These are the simplified steps of calling writeExternal method in ba.writeObject(some_obj):
- Find function binding_id by search name of writeExternal in public namespace
- Get method environment structure by methods[binding_id]
- JIT the method environment to native code, and call it.
You can find relative code in the AVMPlus open source project. In the ClassInfo constructor, it will find m_functionBinding uses public namespace and the kWriteExternal string.
Figure 2. Get kWriteExternal function binding code snippet
Figure 3. Find MethodEnv pointer code snippet
The key sentence in above is MethodEnv* method = obj->vtable->methods[id].
We know that the writeExternal function binding id is wrong after being hidden by the writeExternal property, because when doing search it will find out the public writeExternal property.
This means that exploits now can construct a custom class definition to get a wanted function binding_id value.
From the AVMPlus source code, we can see that it will read the method from obj->vtable->methods[id]. The id value can be controlled, so exploits also can control the MethodEnv* read out. After this point, the vulnerability has become an out-of-bound read case; exploits can control the memory layout to put a MethodEnv* of their choosing in the faked function id slot.
The exploit then uses another custom defined AS3 method to be called using ksome_externalizable_obj as this pointer. It seems to be a type confusion case here now.
In summary, the steps for this exploit are:
- Define class A that implements utils.IExternalizable. Class A defines the writeExternal method and writeExternal property within public namespace. Control the writeExternal property’s order to control the fake function’s binding_id.
- Define class B, and define method B with the malicious code that is to be called. New objects from this class are used to control the memory layout and make sure the method B’s environment structure is to be allocated in the fake binding_id.
- Create a new externalizable object from class A, and then use writeObject(externalizable_object) to trigger the vulnerability.
- The method B will be called, and the attacker can manipulate this pointer of externalizable_object inthis method.
Going Beyond the Vector.<*>
Here is how the attacker used this vulnerability. The sample overwrote the length field of a ByteArray-based object to 0Xfffffff6. They used this to read and write into arbitrary memory locations. The Vector.<*> mitigations are of no use here as the ByteArray length is not protected.
Attackers need not rely on targeting Vector.<*> for exploits in the future. As this attack has shown, there are other objects that can be used (or abused) by attackers. Adobe should protect the ByteArray length and other objects that have the length property.
I constructed a simplified proof-of-concept (PoC) that showcases the vulnerability and debugged it. First, I set the writeExternal property object to be the 28th property. The PoC does not control the binding_id slot memory layout, so it will read out a garbage method environment pointer and cause a crash.
I used a windbg extension to help debug this POC. This extension can help trace and set a breakpoint on AS3 methods. With that, I can easily break into MethodEnv* method = obj->vtable->methods[id].
Figure 4. Debugger output
Mitigations can decrease exploits but they are not silver bullets. History has proved that good or perfect vulnerabilities can always bypass mitigations, making it of utmost importance for users to have multi-layered defense against attacks that employ zero-day exploits. Trend Micro technologies protects users from zero-day exploits by offering protections for all the different layers within an infrastructure.
The existing Sandbox with Script Analyzer engine, which is part of Trend Micro™ Deep Discovery, can be used detect attacks using this Adobe Flash 0day by its behavior without any engine or pattern updates.
Trend Micro Deep Security and Vulnerability Protection, on the other hand, protect user systems from threats that may leverage this Adobe Flash zero-day with the DPI rule 1007119 – Identified Malicious Adobe Flash SWF File.
The SHA1 hashes of files related to this threat are:
- 2DF498F32D8BAD89D0D6D30275C19127763D5568 – detected as SWF_OLOLO.A
- 20F5A9C0E1D2AEF36D15CA149FE71AC6B2A9AF1E – detected as TROJ_SEDNIT.D
- A5FCA59A2FAE0A12512336CA1B78F857AFC06445 – detected as TSPY_SEDNIT.D
With Additional analysis by Stanley Liu
Updated on October 17, 2015, 7:29 P.M. PDT (UTC-7) to add the SHA1 hashes related to this latest Flash exploit.