CORSAIR iCUE Driver Local Privilege Escalation (CVE-2020-8808)

Preview

CORSAIR is considered one of the world’s leading providers for high-performance PC peripherals and components. It offers a complete range of products to equip gamers and content creators, including keyboards, mice, headsets, capture cards, studio controllers, etc. While researching the interface software that is CORSAIR iCUE v3.23.66 (the latest at the time of research), we’ve found that said software installs a driver that will allow low privileged users to map an arbitrary physical memory which leads to local privilege escalation.

We start off by examining the device permissions and can see the device driver is writeable by Everyone group, meaning any low privileged process can interact with said driver by sending IOCTL codes.

​Next, we reverse engineer the device driver to see what IOCTL codes it exposes and if there are any interesting code paths we can hit. The following is the CorsairLLAccess64.sys driver routine for device I/O control requests.

​Once we located the routine that handles IOCTL control codes, we searched for interesting code paths and ultimately found IOCTL control code 0x225374 which is the sum of (0x225348 + 0x10 + 0x1C) as shown below.

Investigating this branch, we notice a call to IoGetRequestorProcessId() function that returns the unique 32-bit process ID for the call thread in EAX.

Followed by a call to the problematic function, that is FUN_1400013e0 which takes six arguments as an input. With the help of dynamic analysis tools, we communicate with the driver via DeviceIoControl() function call and then we use the comments section to record a few arguments used by said function that were interesting to us.

​Now entering this function call, we noticed there are a few checks that we need to fail, otherwise we will end up with 0xc0000023 status code (i.e. STATUS_BUFFER_TOO_SMALL). In essence, we need to make sure the input buffer size is equal to or greater than 0xC and the output buffer size is equal to or greater than 0x8 in DeviceIoControl() function call.

​Once the above conditions are met, we reach MmMapIoSpace() function call which maps a given physical address range to nonpaged system space where we control the PhysicalAddress and NumberOfBytes parameters via the input buffer parameter in DeviceIoControl() function call.

​Followed by a number of function calls that make sure to properly map the physical memory pages onto the calling process virtual address space. Please note the description below was taken from MSDN documentation.

In summary, we can map an arbitrary physical memory from low privileged processes which effectively leads to elevation of privileges. In our proof-of-concept exploit, we located the EPROCESS structures (i.e. the kernel’s representation of a process object) of the LSASS process which runs in SYSTEM context and the PowerShell process within the mapped physical memory range and ultimately performed a token stealing attack to achieve privilege escalation.

​Please note that the above exploit was based heavily on prior work done by Ruben Boonen in the Razer driver bug found here. At that point, we sent the vulnerability details to the vendor and a patch was shared with us in version 3.25.54. Running the proof-of-concept exploit against the patched driver shows we’re no longer able to obtain a handle to the driver from a non-privileged process and, moreover, we receive random error codes every time we run it.

​Inspecting the patched driver, we quickly notice the addition of SeQueryInformationToken() and ExFreePoolWithTag() function calls.

​Following SeQueryInformationToken() references, we land in function FUN_1400010d0 as shown below where there are two calls to said function that presumably check whether the calling process token is elevated.

​Let’s break on the first call inside WinDbg to confirm our assumptions by inspecting the R8 register (i.e. *TokenInformation parameter) which should receive a pointer to a location that contains the address of a buffer that holds the requested information, that is TOKEN_ELEVATION structure (offset 0x14 in Token_Information_Class enumeration type).

​The TOKEN_ELEVATION structure has one DWORD member called TokenIsElevated indicating whether a given token has elevated privileges.

​Now running the proof-of-concept exploit from a non-elevated process returns zero value, whereas running it from an elevated process return nonzero value indicating that the token has elevated privileges.

​It’s worth mentioning in the case of a non-elevated process, we reach the below section where a number of operations are performed to obfuscate 0xc0000022 status code (i.e. STATUS_ACCESS_DENIED) which explains the random error codes we got earlier.

​In essence, when requesting a handle for the patched driver, this check is performed to limit access only to elevated processes (high-integrity level), meaning only those with administrative rights have access to the driver which effectively nullifies the reported vulnerability. Lastly, feel free to reach out to labs@activecyber.us if you have any questions. Also, see the link here for a complete list of ACTIVELabs advisories.
 
Affected Products

  • CORSAIR iCUE version 3.24.52 and older.

Disclosure Timeline

  • 12-10-19: ACTIVELabs submitted a ticket to CORSAIR via support portal

  • 12-12-19: CORSAIR support requested vulnerability details to forward to the appropriate team

  • 12-16-19: ACTIVELabs sent vulnerability details along with proof-of-concept exploit to CORSAIR support

  • 12-17-19: CORSAIR support responded that they will look into it and get back with us

  • 12-31-19: ACTIVELabs requested an update

  • 12-31-19: CORSAIR support responded there is no update for the time being

  • 01-13-20: ACTIVELabs tested version 3.24.52 released on 01/06/2020 and informed CORSAIR support that the driver is indeed still vulnerable

  • 01-14-20: CORSAIR support responded there is no update on this ticket still

  • 01-17-20: CORSAIR support updated ACTIVELabs that the issue has been resolved in version 3.25.54 and asked if we would like a copy of the patch

  • 01-20-20: ACTIVELabs requested to test the patch and provide a timeline on when the patched version will be made public

  • 01-22-20: CORSAIR support responded the ETA for the patch is 01/28/20 and shared a link to download the patch

  • 01-24-20: ACTIVELabs informed CORSAIR support that the patch has nullified the reported vulnerability and an advisory along with blog post will be released once the patch is made public

  • 01-30-20: ACTIVELabs requested an update in regards to patch ETA which was supposed to be released on 01/28/20

  • 01-30-20: CORSAIR support responded that a new update was requested at the last minute and they will share new a ETA once determined

  • 02-06-20: ACTIVELabs requested an update

  • 02-06-20: CORSAIR support responded that a new version will be released today

  • 02-06-20: ACTIVELabs sent CORSAIR a support draft blog post for review

  • 02-06-20: CORSAIR iCUE version 3.25.60 released

  • 02-07-20: ACTIVELabs publishes an advisory on GitHub

  • 02-07-20: ACTIVELabs requested CVE from MITRE

  • 02-07-20: CVE-2020-8808 assigned

  • 02-11-20: ACTIVELabs publishes this blog post

Previous
Previous

Docker Desktop Local Privilege Escalation (CVE-2020-10665)

Next
Next

Viper RGB Driver Local Privilege Escalation (CVE-2019-18845)