Use-after-free (UAF) Vulnerability CVE-2018-8373 in VBScript Engine Affects Internet Explorer to Run Shellcode

by Elliot Cao (Trend Micro Security Research) with Trend Micro’s Zero Day Initiative (ZDI)

We discovered a high-risk Internet Explorer (IE) vulnerability in the wild on July 11, just a day after Microsoft’s July Patch Tuesday. We immediately sent Microsoft the details to help fix this flaw. While this vulnerability, now designated as CVE-2018-8373, affects the VBScript engine in the latest versions of Windows, Internet Explorer 11 is not vulnerable since VBScript in Windows 10 Redstone 3 (RS3) has been effectively disabled by default.

We discovered the exploit in malicious web traffic. The URL is shown as below:

Figure 1. Malicious URL used

Figure 1. Malicious URL used

We found this exploit using heuristics, which led to a more in-depth analysis. Interestingly, we found that this exploit sample uses the same obfuscation technique as exploits for CVE-2018-8174, a VBScript engine remote code execution vulnerability patched back in May.

Figure 2. Comparison of CVE-2018-8373 (left side) and CVE-2018-8174 (right side)

Figure 2. Comparison of CVE-2018-8373 (left side) and CVE-2018-8174 (right side)

Moreover, here’s the sample exploit’s method for running shellcode:

Figure 3. Comparison of how shellcode is run by CVE-2018-8373 (left side) and CVE-2018-8174 (right side)

Figure 3. Comparison of how shellcode is run by CVE-2018-8373 (left side) and CVE-2018-8174 (right side)

We suspect that this exploit sample came from the same creator. Our analysis revealed that it used a new use-after-free (UAF) vulnerability in vbscript.dll, which remained unpatched in the latest VBScript engine.

Vulnerability Root Cause Analysis

We now detail our analysis of this vulnerability, which has been addressed in Microsoft’s August Patch Tuesday. Because the original exploit was heavily obfuscated, we demonstrate a proof of concept (PoC) to explain how this vulnerability can be exploited:

Figure 4. IE vulnerability PoC

Figure 4. IE vulnerability PoC

This PoC defines one class called MyClass, which has one member variable called array and two member functions called Class_Initialize and Default Property Get P. Class_Initialize is a deprecated method, now replaced by the New procedure. It is automatically invoked when an object is first instantiated. In this PoC, the Class_Initialize function is overloaded, and when a call to VBScriptClass::InitializeClass is made, it gets dispatched to the overloaded function instead.

A default property is one class property that can be accessed without specifying it. In this PoC, the Default Property Get function overloads MyClass’s default property. When a call is made to access cls, it is dispatched to the overloaded function instead.

The vulnerability’s trigger flow can be simplified as the following three steps:

1. Set cls = New MyClass

This will call overloaded function Class_Initialize. In Class_Initialize, ReDim array(2) will call vbscript!RedimPreserveArray to create an array whose element’s count is 3:

Figure 5. ReDim array(2) in memory

Figure 5. ReDim array(2) in memory

2. cls.array(2)

It will call vbscript!AccessArray to get the address of the array’s element. In vbscript!AccessArray, it will first check if the index of the array’s element is out of boundary:

Figure 6. Check element index in vbscript!AccessArray

Figure 6. Check element index in vbscript!AccessArray

Then the element’s address is calculated, gets saved on the stack, and returns the following:

Figure 7. Save element address on the stack

Figure 7. Save element address on the stack

3. cls.array(2)=cls

This will call vbscript!AssignVar to set MyClass default property value to cls.array(2). When getting the MyClass default property value, Public Default Property Get P is called and executes the script ReDim array(1) in Public Default Property Get P, which will cause original array.pvData to be freed:

Figure 8. Original pvData is freed

Figure 8. Original pvData is freed

But the address of array(2) is still saved on the stack as described in step two. Public Default Property Get P’s return value will access the freed memory and consequently trigger the use-after-free (UAF) vulnerability in vbscript!AssignVar:

Figure 9. Crash in vbscript!AssignVar

Figure 9. Crash in vbscript!AssignVar

As previously mentioned, vbscript!AccessArray checks if the index of the array’s element is out of boundary. But when getting a default property value of the class, it will trigger the script callback function Default Property Get to modify the array’s length, and not check the array’s element again when accessed in vbscript!AssignVar.

Exploitation Analysis

The exploitation can be simplified with the following three steps:

  1. Use the vulnerability to modify a two-dimensional array’s length to 0x0FFFFFFF.
  2. Implement Read/Write primitives.
  3. Fake CONTEXT structure and execute shellcode.

Let’s talk about the exploitation in detail:

1. Modify a two-dimensional array’s length

First, the vulnerability defines two arrays, which we labeled in the following figures as array1 and array2. The array1 is the array previously described in the PoC, and array2 is a two-dimensional array in which each element’s value is 3.

Figure 10. Definition of array2

Figure 10. Definition of array2

Then it uses script callback function Default Property Get to free original array1.pvData and set array2 to new array1.pvData. Because the size of the original array1.pvData, which is 0x30 Bytes in memory, is the same as array2.SAFEARRAY structure, some of the array2.SAFEARRAY structure will reuse the memory freed in original array1.pvData. Meanwhile, Default Property Get’s return value 0x0FFFFFFFF will cover the structure SAFEARRAYBOUND of array2.SAFEARRAY and modify the two-dimensional array’s length to 0x0FFFFFFF.

Figure 11. Definition of Default Property Get

Figure 11. Definition of Default Property Get

Figure 12. Steps for modifying array’s length

Figure 12. Steps for modifying array’s length

2. RW primitives

Here it gets one array, array1(index_vuln)(0x0FFFFFFE, 2), whose length is tempered by UAF. By searching array1’s element, the index_vuln can be found in the following script:

Figure 13. Searching array1(index_vuln)(0x0FFFFFFE, 2)

Figure 13. Searching array1(index_vuln)(0x0FFFFFFE, 2)

Then it uses array1(index_vuln)(0x0FFFFFFE, 2) to realize out-of-bounds (OOB) and find two array’s elements for type confusion.

Figure 14 and 15. Searching two array’s elements

Figure 14 and 15. Searching two array’s elements

Here the vulnerability gets two array’s elements: array1(index_B)(0, 0) and array1(index_vuln)(index_A, 0), which have a distance of 8 Bytes in memory. The full exploitation of searching in memory is shown below:

Figure 16. Demonstration of the way it searches in memory

Figure 16. Demonstration of the way it searches in memory

Finally, it uses the two array’s elements to implement read and write primitives by type confusion:

Figure 17. Implementation of RW Primitives

Figure 17. Implementation of RW Primitives

3. Run shellcode

It uses read primitives to leak modules’ addresses:

Figure 18. Leak modules’ addresses

Figure 18. Leak modules’ addresses

By modifying some VARIANT’s VarType to 0x4d and value to 0, vbscript!VAR::Clear will be called, then the call stack return address will be modified to NtContinue’s address and faked CONTEXT structure to run shellcode:

Figure 19. Modify VARIANT

Figure 19. Modify VARIANT

Figure 20. Run shellcode

Figure 20. Run shellcode

Based on our analysis, this vulnerability can be steadily exploited. Moreover, since it is the second VB engine exploit found in the wild this year, it is not far-fetched to expect other vulnerability findings in the VB engine in the future.

Mitigation and Solutions

As a first line of defense, we recommend applying the latest security patches once they’re available to prevent exploits. Users can also employ solutions that defend against possible exploits. A proactive, multilayered approach to security is key against threats that exploit vulnerabilities — from the gateway, endpoints, networks, and servers. Trend Micro™ OfficeScan™ with XGen™ endpoint security has Vulnerability Protection that shields endpoints from identified and unknown vulnerability exploits even before patches are deployed. Trend Micro’s endpoint solutions such as Trend Micro™ Smart Protection Suites and Worry-Free™ Business Security protect end users and businesses from these threats by detecting and blocking malicious files and all related malicious URLs. The Trend Micro™ Deep Discovery™ solution provides detection, in-depth analysis, and proactive response to today’s stealthy malware and targeted attacks in real time. It provides a comprehensive defense tailored to protect organizations against targeted attacks and advanced threats through specialized engines, custom sandboxing, and seamless correlation across the entire attack life cycle.

Trend Micro™ Deep Security and Vulnerability Protection protect user systems from threats that may exploit the vulnerability via the following DPI rule:

  • 1009218 – Microsoft Windows VBScript Engine Use-After-Free Vulnerability

Trend Micro™ TippingPoint™ customers are protected from threats that may exploit the vulnerability via this MainlineDV filter:

  • 32721: Microsoft VBScript Engine Sub Default Property Use-After-Free Vulnerability

Indicator of Compromise (IoC)

Related hash (SHA256):

  • 0d6fe137790e2ebdf4fac2dd500656f3a6f74c0d1598251929ea3558f965675f – detected as HTML_EXPLOIT.YYRV

The post Use-after-free (UAF) Vulnerability CVE-2018-8373 in VBScript Engine Affects Internet Explorer to Run Shellcode appeared first on .