CVE-2019-1458: Win32k Uninitialized Variable in Window Switching

This page has been moved to our new site. Please click here to go to the new location.
Posted by Maddie Stone, Project Zero (2020-07-27)

Disclosure or Patch Date: 10 December 2019
Product: Microsoft Windows
Affected Versions: 
  • For Windows 10 1607 x64, KB4525236 and previous
  • For Windows 7 x64, KB4525233 and previous
First Patched Version:
Issue/Bug Report: N/A 
Patch CL: N/A
Bug-Introducing CL: N/A
Proof-of-Concept: https://github.com/piotrflorczyk/cve-2019-1458_POC
Exploit Sample: N/A
Access to the exploit sample? No 
Reporter(s): Anton Ivanov and Alexey Kulaev of Kaspersky Lab (Thanks to Kaspersky Lab and @florek_pl for sharing detailed analyses!)

Bug Class: Uninitialized variable
Vulnerability Details:

The bug is that a field, *(gpsi + 0x154), in a global structure, tagSERVERINFO, which defines information about system windows for the operating system, is uninitialized. This then permits a user-space application to set extra window data in the task-switch window (FNID_SWITCH, 0x280), which is usually only able to be set by the kernel. This extra window data is a pointer which is then dereferenced and written to. This gives a limited write primitive to an arbitrary memory address.

Is the exploit method known? Yes
Exploit method: 
The details about the exploitation method were posted by Kaspersky Lab in their post “The Zero Day Exploits of Wizard Opium”.
To exploit this bug, a Windows kernel memory corruption, Bitmaps were used to both bypass ASLR and get arbitrary kernel read and write. This post describes the technique in detail. In their blog post, Kaspersky explains that the exploit supports two different methods for ASLR bypass:
  1. For older builds, the Bitmap kernel addresses are leaked by the GdiSharedHandlerTable
  2. Creating an AcceleratorTable object and using gSharedInfoHandleTable to leak its kernel address, then freeing the AcceleratorTable and allocating a Bitmap in its place.

To elevate privileges, the exploit steals the system token from the EPROCESS object in a project running as SYSTEM. This is a known technique that has been documented in many places such as here.

How do you think you would have found this bug?  
SetWindowLongPtr bugs have been very prevalent over the years. Therefore, I think it would be quite easy for a skilled researcher to identify through manual reverse engineering/auditing that the FNID_SWITCH field in gpsi was initially uninitialized and then follow the code path through to see that that would permit the attacker-controlled pointer dereference. Due to the different conditions and the order of system calls, I think it would be more difficult to fuzz this bug rather than manually reverse it.

(Historical/present/future) context of bug: 
Kaspersky Lab found this bug exploited in conjunction with the Chrome 0-day CVE-2019-13720 [P0 Root Cause Analysis]. The Chrome exploit embedded the exploit for this vulnerability, CVE-2019-1458, as the elevation of privilege. 

This exploit was discovered by Kaspersky in November 2019. Windows 7, which this exploit targeted, was hitting end-of-life in January 2020. It’s possible that the attackers decided to just go ahead and use this exploit even if it was “noisy” or potentially easier to detect, knowing that the EOL was coming. 

Areas/approach for variant analysis: 
When patching this bug, Microsoft added initialization for 2 other system window types in addition to FNID_SWITCH. There are more than just these system window types so it’d be worth exploring why only these ones were selected for initialization and if:
  1. Any other system window types still have the uninitialized variable vulnerability, or 
  2. The other window types who now have initialization have any SetWindowLongPtr vulnerabilities.

Another interesting area for variant analysis would be in the task switching code. I originally attempted to patch-diff this vulnerability when the patch was first released, but ended up reverse engineering another bug in the task-switching code [blog post]. There appears to be quite a bit of legacy code still in the module. With at least 2 bugs in it in 3 months, and one exploited in the wild, it seems like a ripe area for analysis. 

Note: Project Zero did not perform either of these analyses. 

Found variants: N/A

Structural improvements:
  • This vulnerability was not exploited against the latest Windows release due to mitigations that have been added, such as Win32k lockdown for sandboxed code and they’ve mitigated the two ASLR bypass methods this exploit uses. This shows that Microsoft’s mitigations and structural improvements are working.

Potential detection methods for similar 0-days: 
  • User applications that are creating system windows such as FNID_SWITCH

Other references: 

No comments:

Post a Comment