Developing Drivers with the Windows Driver Foundation: WDF Fundamentals
Every driver must be secure. Users trust drivers to transfer data between their applications and their devices. An insecure driver can expose sensitive data such as the user’s passwords or account numbers to theft. Insecure drivers can also expose users to other security exploits such as denial of service or spoofing.
Drivers pose more security risks than applications, for the following reasons:
Drivers can typically be accessed by any user and can be used by multiple users at the same time.
Users are typically unaware that they are using a driver.
Security is closely related to reliability. Although the two requirements sometimes involve different programming issues, an insecure driver cannot be reliable, and vice versa. For example, a driver that crashes the system in effect causes a denial-of-service attack.
This book cannot cover every aspect of driver security; that would be a book in itself. However, understanding a few basics can make a big difference. The core precept of WDF driver security is that every driver must work to prevent unauthorized access to devices, files, and data. WDF is designed to contribute to driver security by providing safe defaults and extensive parameter validation.
This section briefly discusses WDF security features. For more information, see the WDK, which provides fundamental guidelines that apply to both UMDF and KMDF drivers.
See “Creating Reliable and Secure Drivers” in the WDK for security guidelines—online at http://go.microsoft.com/fwlink/?LinkId=80063. See also Writing Secure Code, Second Edition, by Howard and LeBlanc, for a general discussion of secure coding practices—available at http://go.microsoft.com/fwlink/?LinkId=80091.
Unless a WDF driver specifies otherwise, the framework requires administrator privileges for access to sensitive data such as exposed names, device IDs, or WMI management interfaces. The WDF default security settings provide secure names for kernel-mode device objects so that only kernel-mode components and administrators can access these objects.
Chapter 6 provides information about device object security.
The framework automatically provides default handling for all I/O requests that the driver does not handle. The default handling prevents unexpected requests from entering a WDF driver that might misinterpret them. However, WDF does not protect drivers from ill-formed requests—when WDF drivers handle requests, they are responsible for handling them appropriately.
By default, UMDF drivers run in the LocalService account, which supports minimum security privileges. However, when a client’s application opens a UMDF driver, it can grant the driver permission to impersonate the client. That action allows the driver to perform tasks that require a higher level of privilege.
Chapter 8 discusses impersonation.
Buffer overflows are a major source of security problems in drivers as well as in applications. All WDF functions or methods that use buffers have a length parameter that specifies the required minimum buffer length. For I/O requests, WDF extends this practice by placing I/O buffers in framework memory objects. The data access methods exposed by memory objects automatically validate buffer length and determine whether the permissions that are specified for the buffer allow write access to the underlying memory.
One of the most common driver security problems occurs when kernel-mode drivers fail to properly handle user-mode buffers that I/O control requests carry. This is particularly true for requests that specify neither-buffered-nor-direct I/O (that is, METHOD_NEITHER I/O). Because the pointers to user-mode buffers in this type of request are inherently unsafe, KMDF drivers do not have direct access to the pointers by default. Instead, WDF provides methods to allow a WDF driver to safely probe the buffer and lock it into memory.