Author John Neff
Another day, another Windows driver vulnerability. Cyber Security professionals found their Windows networks susceptible to the PrintNightmare driver vulnerability. CVE-2021-34527 (known as “PrintNightmare”) is the latest hack du jour, attacking the Windows Print Spooler builtin service in particular. This allowed unprivileged users to install a “printer” driver from System32, thereby granting hackers system-level access to run arbitrary code, install malware, create accounts, and access/change/delete data. Kernel level code has complete control over the memory space and therefore the system. Kernel access is inherent in drivers or obtained through the Windows API. Drivers and the Windows API usually work hand in hand, handling calls from user space applications to the kernel and subsequently the hardware. Our focus in this article is on Windows Drivers, and briefly touch on the vulnerabilities exposed by the Windows API.
A driver is a piece of software that communicates on behalf of the operating system and devices used in the system and coordinates the data and actions between them. Microsoft defines three kinds of drivers: Function, Filter, and Bus.
Function drivers handle read and write operations directly to and from the device. For instance, function drivers would be the software level communicators using predefined hardware “functions”. A function driver for a device can be implemented as a driver and minidriver pair, where the minidriver is linked to the second driver, which is a Dynamic-link library (DLL). A minidriver handles device-specific features on behalf of a system-supplied driver.
Filter drivers perform “auxiliary processing”, and act, sometimes in groups, as an intermediary that sits above the function driver granting access to device functionality and performing data processing. Filter drivers also are capable of triggering device behavior changes. Upper level filter drivers perform operations on the data and provide new functionality. A lower-level filter driver can alter and perform integrity checks of data read from the hardware. For example, an upper-level filter driver could change the colors received from an imaging device in a similar manner to an Instagram or Snapchat filter. A lower-level filter driver in this same context would perform communication checks to ensure packets are uninterrupted.
Another type of filter driver is the Bus (e.g. USB, PCI, PCIe) Filter driver, which may be added on top of the bus driver. A Bus driver services an I/O bus controller, adapter, or bridge. Bus drivers provide per-slot functionality, are device-independent, and detect/report child devices connected to the bus. If a device is being driven in raw mode, it means it operates without function, upper-level, or lower-level drivers. In this case, all raw-mode I/O is performed by the bus drivers.
Each of these drivers create the many layers between software and hardware, and each serve a specific purpose. Microsoft has written many drivers that correspond with published hardware standards. This makes life easier for manufacturers by providing off-the-shelf drivers for a massive ecosystem of computers capable of using their device. For instance, Microsoft introduced Plug n’ Play (PNP) and created their own generic DOS/device manager drivers in WIndows 95. Today, Microsoft offers drivers for 3D print devices, ACPIs, audio, battery drivers, biometrics, bluetooth, imaging, sd cards, serial ports, kernel-mode drivers, network drivers, netadapters, global navigation satellite systems, and more. Microsoft designed-and-tested drivers usually offer administrators some semblance of confidence for their networks. Windows 10 added a source of removable device logging with Advanced Audit Policy Configuration, which logs an event every time PNP successfully detects a device for the first time. As soon as the infosec community identifies a vulnerable kernel vector, more tools are at the administrator's fingertips to identify and remediate their infrastructure. That is to say, many of the pre-installed drivers offer great utility to users, administrators, and hardware manufacturers alike.
In the case of CVE-2021-34527, the Windows Print Spooler was missing an access control list that checks for AddPrinterDriverEx(), RpcAddPrinterDriver(), and RpcAsyncAddPrinterDriver() Windows API functions used to install local or remote printer drivers to a print server.
A malicious DLL is able to bypass a permission check when it is added to the C:\Windows\System32\spool\drivers folder, which then is loaded as a print driver by the PrintNightmare exploit. To exploit this vulnerability, requests can be sent directly to the local service via RPC or LRPC for remote code execution (RCE) or local privilege escalation (LPE).
Resolving this issue begins with installing the July 6, 2021 Out-of-band and later security updates. These protect against the remote code execution vulnerability in the Windows Print Spooler service (spoolsv.exe). In this way, non-administrators, to include delegated admin groups, cannot install signed and unsigned printer drivers to a print server. By default, administrator credentials are required to install signed and unsigned drivers to a print server.
Indicators of Vulnerability
NoWarningNoElevationOnInstall = 0 (DWORD)
UpdatePromptSettings = 0 (DWORD)
Group Policy: You have not configured the Point and Print Restrictions Group Policy
If both of these conditions are true, then you are not vulnerable to CVE-2021-34527 and no further action is needed. Microsoft strongly recommends applying this policy to all machines, starting with devices that currently host the print spooler service. Moreover, this policy change does not require a restart of the device or the print spooler service after applying these settings. Optionally, configuring the RestrictDriverInstallationToAdministrators registry value to 1 will override all Point and Print Restrictions Group policy settings and ensure only administrators can install printer drivers, as well.
Driver Security & Hackability
In general, drivers are susceptible to many of the common attacks leveraged by malicious actors. Drivers are typically written in C or C++ on Windows, which place drivers smack dab in the venn diagram of C family vulnerabilities. For example, an infamous hacker favorite rears its unbounded head once again in the form of buffer overflows. This weakness is characterized by an unchecked input where the buffer length becomes an attack vector. This is fatal in drivers because they live in Kernel address space, putting the integrity and stability of the system into jeopardy. Optimizing kernel memory usage by performing input checks and using a secondary minidriver to monitor I/O are some ways to mitigate this class of attack at the driver level.
If you are a computer hardware enthusiast you will be excited for the next generation of Ryzen Threadripper CPU’s adding cores to their cores. Now imagine you have all 64 cores and 128 threads trying to access the driver to make updates at the same time. This is called a race condition, some of the threads will access the hardware data while others will fail. A more nefarious actor may see this as an opportunity to inject themselves into the chaos and be the last one standing. Race conditions present instability and insecurity. Therefore, drivers should implement locking mechanisms for the data stored and accessed.
As we’ve learned with PrintNightmare, knowing who or what is installing drivers is critical to computer security. Windows Print Spooler service did not perform privilege checks for usage of RpcAddPrinterDriverEx(). Verify that all users, services, or processes are running in the context of the authority expected when they attempt to perform a desired action. Likewise, ensure that you are not granting more access than is required. The developers implementing the code must defend against common exploitable vulnerabilities and weaknesses to improve both driver security and reliability. One strategy is not sufficient by itself, it must work in tandem with an interconnected system of checks. At the same time, security professionals must implement several safeguards to ensure complete coverage.
With daily life and work becoming increasingly dependent on computer augmentation, cyber attacks pose deeper and menacing threats than ever before. A malicious actor with intermediate coding skills who compiles their own driver can install kernel level software to infiltrate your computer, as demonstrated by the PrintNightmare attack. Drivers power the devices they work with, but with great power comes great responsibility. One of the first and easiest steps to counter this threat is to verify your operating system and drivers are up-to-date and patched. Further steps require administrators to restrict user access to SAM, system, and security files. The weakest link in the chain of cyber security is human error, whether they be user or developer, and taking these initial steps can greatly improve your security posture against this attack.
Vulnerable systems can remove the Users ACL to read these sensitive files by executing the following commands:
icacls %windir%\system32\config\sam /remove "Users"
icacls %windir%\system32\config\security /remove "Users"
icacls %windir%\system32\config\system /remove "Users"
Once the ACLs have been corrected for these files, any VSS shadow copies of the system drive must be deleted to protect a system against exploitation. This can be accomplished with the following command, assuming that your system drive is c::
vssadmin delete shadows /for=c: /Quiet
Confirm that VSS shadow copies were deleted by running vssadmin list shadows again. Note that any capabilities relying on existing shadow copies, such as System Restore, will not function as expected. Newly-created shadow copies, which will contain the proper ACLs, will function as expected.
For additional information, reference these websites:
About the Author: John Neff is a Cyber Security Analyst located in San Antonio, TX. John's passion for cyber security led him to serve as chapter-lead for San Antonio