CVE-2020-17087 Windows Kernel local privilege escalation 0day

2020-11-11T00:00:00
ID AKB:B72B19ED-8E0B-4C11-9C2D-95A25BCC42A6
Type attackerkb
Reporter AttackerKB
Modified 2020-11-17T00:00:00

Description

CVE-2020-17087 is a pool-based buffer overflow vulnerability in the Windows Kernel Cryptography Driver (cng.sys). The vulnerability arises from input/output controller (IOCTL) 0x390400 processing and could allow a local attacker to escalate privileges, including for sandbox escape. The vulnerability was initially released as a zero-day by Google’s Project Zero team; it was patched on November 10, 2020, as part of Microsoft’s November 2020 Patch Tuesday release.

Recent assessments:

zeroSteiner at October 30, 2020 9:13pm UTC reported:

An error exists within cng!CfgAdtpFormatPropertyBlock where buffer is allocated from a value that is truncated to be 16-bits. The function then goes on and performs a binary to ASCII hex conversion, writing the ASCII hex characters to this buffer. While performing the conversion, the original buffer’s correct length is used causing the write to continue out of bounds.

The vector for this vulnerability is local. A malicious attacker would first have to have code execution on the target system from any context including that of a sandboxed application. From there they would open a handle to \\.\GLOBALROOT\Device\Cng before issuing the 0x390400 IOCTL with a crafted input buffer. The crafted input buffer contains a size parameter as one of the fields that when set to 0x2aab or greater will trigger the overflow.

Exploitation of this bug won’t be easy due to it being a heap based memory corruption within the kernel’s NonPagedPool. The attacker has partial control over the size of the allocation as constrained by ((size * 6) & 0xffff).

This vulnerability was originally reported by Google’s Project Zero who also reported that it is being actively exploited in the wild. The original report is on their tracker. The live in the wild exploitation is reportedly targeted and not related to the US elections. A patch is expected to be release on November 10th, 2020.

While the vulnerable code appears to be present within Windows 7 SP1 x64 as verified through static analysis. The original PoC provided by Google’s Project Zero team, does not trigger the bug on this platform. Within the callstack the chain is accessible, however a difference within the implementations is causing cng!BCryptSetContextFunctionProperty to branch leading to the path to cng!CfgAdtReportFunctionPropertyModification being missed.

Detection

Attempted exploitation of this vulnerability can be detected through auditing event ID 5069. This must be configured in order to detect exploitation attempts. To enable it, start secpol.msc, then navigate to Security Settings > Advanced Audit Policy Configuration > System Audit Policies > Policy Change. Set Audit Other Policy Change Events to enable both “Success” and “Failure”. With this change in place, event ID 5069 will be loaded to the standard Windows Security Log that is accessible through the event viewer.

Exploitation attempts can then be identified through the length of the reported “value” field.

Proof of Concept

The following is a port of the original Proof of Concept released by Google Project Zero into Python and updated to demonstrate the vulnerability on both Windows 7 SP1 and Windows 10.

import ctypes
import random

# https://github.com/zeroSteiner/mayhem
from mayhem.windll import *

value = (ctypes.c_ubyte * 0x2aab)()
bcrypt.BCryptSetContextFunctionProperty(
    bcrypt.CRYPT_LOCAL,
    'Default',
    bcrypt.BCryptInterface.Cipher,
    'AES',
    "XXX_{:08x}".format(random.randint(0, 0xffffffff)),
    len(value),
    value
)

Instead of directly issuing the IOCTL, this variant uses the bcrypt!BCryptSetContextFunctionProperty function with the appropriate arguments. Randomizing the pszProperty argument helps to ensure that the vulnerability is triggered exactly once each time the code is run.

lvarela-r7 at November 03, 2020 8:21pm UTC reported:

An error exists within cng!CfgAdtpFormatPropertyBlock where buffer is allocated from a value that is truncated to be 16-bits. The function then goes on and performs a binary to ASCII hex conversion, writing the ASCII hex characters to this buffer. While performing the conversion, the original buffer’s correct length is used causing the write to continue out of bounds.

The vector for this vulnerability is local. A malicious attacker would first have to have code execution on the target system from any context including that of a sandboxed application. From there they would open a handle to \\.\GLOBALROOT\Device\Cng before issuing the 0x390400 IOCTL with a crafted input buffer. The crafted input buffer contains a size parameter as one of the fields that when set to 0x2aab or greater will trigger the overflow.

Exploitation of this bug won’t be easy due to it being a heap based memory corruption within the kernel’s NonPagedPool. The attacker has partial control over the size of the allocation as constrained by ((size * 6) & 0xffff).

This vulnerability was originally reported by Google’s Project Zero who also reported that it is being actively exploited in the wild. The original report is on their tracker. The live in the wild exploitation is reportedly targeted and not related to the US elections. A patch is expected to be release on November 10th, 2020.

While the vulnerable code appears to be present within Windows 7 SP1 x64 as verified through static analysis. The original PoC provided by Google’s Project Zero team, does not trigger the bug on this platform. Within the callstack the chain is accessible, however a difference within the implementations is causing cng!BCryptSetContextFunctionProperty to branch leading to the path to cng!CfgAdtReportFunctionPropertyModification being missed.

Detection

Attempted exploitation of this vulnerability can be detected through auditing event ID 5069. This must be configured in order to detect exploitation attempts. To enable it, start secpol.msc, then navigate to Security Settings > Advanced Audit Policy Configuration > System Audit Policies > Policy Change. Set Audit Other Policy Change Events to enable both “Success” and “Failure”. With this change in place, event ID 5069 will be loaded to the standard Windows Security Log that is accessible through the event viewer.

Exploitation attempts can then be identified through the length of the reported “value” field.

Proof of Concept

The following is a port of the original Proof of Concept released by Google Project Zero into Python and updated to demonstrate the vulnerability on both Windows 7 SP1 and Windows 10.

import ctypes
import random

# https://github.com/zeroSteiner/mayhem
from mayhem.windll import *

value = (ctypes.c_ubyte * 0x2aab)()
bcrypt.BCryptSetContextFunctionProperty(
    bcrypt.CRYPT_LOCAL,
    'Default',
    bcrypt.BCryptInterface.Cipher,
    'AES',
    "XXX_{:08x}".format(random.randint(0, 0xffffffff)),
    len(value),
    value
)

Instead of directly issuing the IOCTL, this variant uses the bcrypt!BCryptSetContextFunctionProperty function with the appropriate arguments. Randomizing the pszProperty argument helps to ensure that the vulnerability is triggered exactly once each time the code is run.

Assessed Attacker Value: 4
Assessed Attacker Value: 4Assessed Attacker Value: 3