Compartir a través de


Lista de verificación de seguridad del conductor

En este artículo se proporciona una lista de comprobación de seguridad de controladores para que los desarrolladores de controladores ayuden a reducir el riesgo de que los controladores se vean comprometidos.

Introducción a la seguridad del controlador

Un error de seguridad es cualquier error que permite a un atacante hacer que un controlador funcione mal de forma que hace que el sistema se bloquee o se vuelva inutilizable. Además, las vulnerabilidades en el código de controlador pueden permitir que un atacante obtenga acceso al kernel, lo que crea una posibilidad de poner en peligro todo el sistema operativo. Cuando la mayoría de los desarrolladores trabajan en su controlador, su enfoque consiste en conseguir que el controlador funcione correctamente y no en si un atacante malintencionado intentará aprovechar vulnerabilidades dentro de su código.

Sin embargo, una vez que se lanza un controlador, los atacantes pueden intentar investigar e identificar errores de seguridad. Los desarrolladores deben tener en cuenta estos problemas durante la fase de diseño e implementación para minimizar la probabilidad de estas vulnerabilidades. El objetivo es eliminar todos los errores de seguridad conocidos antes de que se lance el controlador.

La creación de controladores más seguros requiere la cooperación del arquitecto del sistema (pensando conscientemente en posibles amenazas al controlador), el desarrollador que implementa el código (codificando de forma defensiva las operaciones comunes que pueden ser la fuente de vulnerabilidades de seguridad) y el equipo de prueba (intentando encontrar de forma proactiva puntos débiles y vulnerabilidades). Al coordinar correctamente todas estas actividades, la seguridad del conductor se mejora considerablemente.

Además de evitar los problemas asociados a un controlador que se está atacando, muchos de los pasos descritos, como el uso más preciso de la memoria del kernel, aumentarán la confiabilidad del controlador. Esto reducirá los costos de soporte técnico y aumentará la satisfacción del cliente con su producto. Completar las tareas de la lista de comprobación siguiente le ayudará a lograr todos estos objetivos.

Lista de comprobación de seguridad:Complete la tarea de seguridad descrita en cada uno de estos temas.

casilla sin marcar que representa un elemento en la lista de verificación de seguridad.Confirme que se requiere un controlador de núcleo

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Usar los marcos del controlador

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Controlar el acceso solo a los controladores del software

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. No firmar el código del controlador de prueba de producción

casilla sin marcar que representa un elemento en la lista de verificación de seguridad.Realizar análisis de amenazas

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Seguir las directrices de codificación segura del controlador

casilla de verificación sin marcar que representa un elemento en la lista de comprobación de seguridad.Implementar código compatible con HVCI

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Seguir procedimientos recomendados de código específicos de la tecnología

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Realizar una revisión del código del mismo nivel

casilla sin marcar que representa un elemento en la lista de comprobación de seguridad.Administrar el control de acceso del controlador

casilla sin marcar que indica un elemento en la lista de comprobación de seguridad.mejorar la seguridad de la instalación de dispositivos

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Ejecutar la firma adecuada del controlador de versión

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Utilizar CodeQL para comprobar el código del controlador

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Agregar anotaciones SAL al código del controlador

casilla sin marcar que representa un elemento en la lista de comprobación de seguridad.Utilice el verificador de controladores para verificar vulnerabilidades

casilla sin marcar que representa un elemento en la lista de comprobación de seguridad.Comprobar código con el analizador binario BinSkim

Casilla sin marcar que representa un elemento en la lista de comprobación de seguridad.Verificar código con las pruebas del programa de compatibilidad de hardware

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Comprender cómo se notifican los controladores mediante el Centro de informes de controladores vulnerables y malintencionados de Microsoft

Casilla sin marcar que representa un elemento en la lista de comprobación de seguridad.Revisar recursos seguros de codificación

Casilla de comprobación sin marcar que representa un elemento en la lista de comprobación de seguridad. Revisar el Resumen de conclusiones clave

Confirmación de que se requiere un controlador de kernel

elemento de lista de comprobación de seguridad n.º 1:Confirmar que se requiere un controlador de kernel y que un enfoque de riesgo menor, como el servicio o la aplicación de Windows, no es una opción mejor.

Los controladores residen en el kernel de Windows, y tener un problema al ejecutarse en el kernel expone todo el sistema operativo. Si hay alguna otra opción disponible, es probable que sea menor el costo y tenga menos riesgo asociado que crear un nuevo controlador de kernel. Para obtener más información sobre el uso de los controladores de Windows integrados, consulte ¿Necesita escribir un controlador?.

Para obtener información sobre el uso de tareas en segundo plano, consulte Como apoyar su aplicación con tareas en segundo plano.

Para obtener información sobre el uso de servicios de Windows, vea Services.

Usar los marcos del controlador

Elemento de la lista de comprobación de seguridad n.º 2:Utiliza los frameworks de controladores para reducir el tamaño del código y aumentar su fiabilidad y seguridad.

Usa el Windows Driver Frameworks para reducir el tamaño de tu código y aumentar su confiabilidad y seguridad. Para empezar, revise Uso de WDF para desarrollar un controlador. Para obtener información sobre el uso del marco del controlador en modo de usuario de menor riesgo (UMDF), consulte Elección de un modelo de controlador.

Escribir un controlador Windows Driver Model (WDM) antiguo requiere más tiempo, es más costoso y casi siempre implica volver a crear el código que esté disponible en los marcos del controlador.

El código fuente de Windows Driver Framework es de código abierto y está disponible en GitHub. Este es el mismo código fuente desde el que se compila la biblioteca en tiempo de ejecución de WDF que se incluye en Windows 10. Puede depurar el controlador de forma más efectiva si puede seguir las interacciones entre el controlador y WDF. Descárguelo de https://github.com/Microsoft/Windows-Driver-Frameworks.

Controlar el acceso solo a los controladores del software

elemento de lista de comprobación de seguridad n.º 3:Si se va a crear un controlador de solo software, se debe implementar un control de acceso adicional.

Los controladores de kernel de solo software no usan plug-and-play (PnP) para asociarse con identificadores de hardware específicos y pueden ejecutarse en cualquier equipo. Este controlador podría usarse con fines distintos de los previstos originalmente, creando un vector de ataque.

Dado que los controladores de kernel de solo software contienen riesgos adicionales, deben limitarse a ejecutarse en hardware específico (por ejemplo, mediante un identificador de PnP único para habilitar la creación de un controlador PnP o comprobando la tabla SMBIOS para ver la presencia de hardware específico).

Por ejemplo, imagine que OEM Fabrikam quiere distribuir un controlador que permita una utilidad de overclocking para sus sistemas. Si este controlador de solo software se ejecutara en un sistema desde un OEM diferente, la inestabilidad del sistema o los daños podrían resultar. Los sistemas de Fabrikam deben incluir un identificador de PnP único para habilitar la creación de un controlador PnP que también es actualizable a través de Windows Update. Si esto no es posible y Fabrikam crea un controlador heredado, ese controlador debe encontrar otro método para comprobar que se está ejecutando en un sistema Fabrikam (por ejemplo, mediante el examen de la tabla SMBIOS antes de habilitar cualquier funcionalidad).

No firmar el código del controlador de prueba de producción

Elemento de la lista de comprobación de seguridad n.º 4:no firme el código de producción del controlador del kernel para el desarrollo, pruebas y fabricación.

El código del controlador de kernel que se usa para el desarrollo, las pruebas o la fabricación pueden incluir funcionalidades peligrosas que suponen un riesgo de seguridad. Este código peligroso nunca debe firmarse con un certificado de confianza para Windows. El mecanismo correcto para ejecutar código de controlador peligroso es deshabilitar el arranque seguro UEFI, habilitar bcD "TESTSIGNING" y firmar el código de desarrollo, prueba y fabricación mediante un certificado que no es de confianza (por ejemplo, uno generado por makecert.exe).

El código firmado por un Certificado de los Editores de Software (SPC) de confianza o una firma de Windows Hardware Quality Labs (WHQL) no debe facilitar la elusión de las tecnologías de seguridad e integridad de código de Windows. Antes de firmar el código con una firma SPC o WHQL confiable, primero asegúrese de que cumpla con las pautas de Creación de controladores en modo kernel confiables. Además, el código no debe contener comportamientos peligrosos, descritos a continuación. Para obtener más información sobre la firma del controlador, consulte Ejecución de la firma adecuada del controlador de versión más adelante en este artículo.

Entre los ejemplos de comportamiento peligroso se incluyen los siguientes:

  • Proporcionar la capacidad de asignar memoria arbitraria del kernel, física o del dispositivo al modo de usuario.
  • Proporcionar la capacidad de leer o escribir memoria arbitraria del kernel, física o del dispositivo, incluida la entrada y salida del puerto (E/S).
  • Proporcionar acceso al almacenamiento que omite el control de acceso de Windows.
  • Proporcionar la capacidad de modificar el hardware o el firmware que el controlador no se diseñó para administrar.

Realizar análisis de amenazas

Elemento de la lista de comprobación de seguridad n.º 5:modifique un modelo de amenazas de controlador existente o cree un modelo de amenazas personalizado para el controlador.

Al considerar la seguridad, una metodología común consiste en crear modelos de amenazas específicos que intentan describir los tipos de ataques que son posibles. Esta técnica es útil al diseñar un controlador porque obliga al desarrollador a tener en cuenta los posibles vectores de ataque contra un controlador de antemano. Después de identificar posibles amenazas, un desarrollador de controladores puede considerar los medios de defensa contra estas amenazas para reforzar la seguridad general del componente de controlador.

En este artículo se proporcionan instrucciones específicas del controlador para crear un modelo de amenazas ligero: Modelado de amenazas para controladores. En el artículo se proporciona un diagrama de modelo de amenazas de un controlador de ejemplo que se puede utilizar como punto de partida para su controlador.

diagrama de flujo de datos de ejemplo que ilustra un controlador hipotético en modo kernel.

Los procedimientos recomendados del ciclo de vida de desarrollo de seguridad (SDL) y las herramientas asociadas se pueden usar en IHD y OEM para mejorar la seguridad de sus productos. Para obtener más información, consulte Recomendaciones de SDL para OEM.

Seguir las directrices de codificación segura del controlador

elemento de lista de comprobación de seguridad n.º 6:Revise el código y quite las vulnerabilidades de código conocidas.

La actividad principal de la creación de controladores seguros es identificar áreas en el código que deben cambiarse para evitar vulnerabilidades de software conocidas. Muchas de estas vulnerabilidades de software conocidas tienen que ver con el mantenimiento de un seguimiento estricto del uso de la memoria para evitar problemas con terceros que sobrescriban o comprometan de otro modo las ubicaciones de memoria que utiliza su controlador.

Las herramientas de análisis de código, como CodeQL y pruebas específicas del controlador, se pueden usar para ayudar a localizar, algunas, pero no todas, de estas vulnerabilidades. Estas herramientas y pruebas se describen más adelante en este tema.

Búferes de memoria

Usar el método adecuado para acceder a los búferes de datos con ICTL

Una de las principales responsabilidades de un controlador de Windows es transferir datos entre las aplicaciones en modo de usuario y los dispositivos de un sistema. Los tres métodos para acceder a los búferes de datos se muestran en la tabla siguiente.

Tipo de búfer IOCTL Resumen Para obtener más información
METHOD_BUFFERED Recomendado para la mayoría de las situaciones Uso de E/S almacenada en búfer
METHOD_IN_DIRECT o METHOD_OUT_DIRECT Se utiliza en algunas E/S de hardware de alta velocidad Uso de E/S directa
METHOD_NEITHER Evitar si es posible Sin uso de búfer ni E/S directa

En general, se recomienda la E/S almacenada en búfer, ya que proporciona los métodos de almacenamiento en búfer más seguros. Pero incluso cuando se usa la E/S almacenada en búfer existen riesgos, como punteros integrados, que deben mitigarse.

Para obtener más información sobre cómo trabajar con búferes en ioCTLs, consulte métodos de para acceder a búferes de datos.

Errores en el uso de E/S con búfer IOCTL

  • Compruebe el tamaño de los búferes relacionados con IOCTL. Para obtener más información, consulte Error al comprobar el tamaño de los búferes.

  • Inicialice correctamente los búferes de salida. Para obtener más información, vea Error al inicializar los búferes de salida.

  • Valide correctamente los búferes de longitud variable. Para obtener más información, consulte Error al validar búferes de longitud variable

  • Al usar E/S almacenada en búfer, asegúrese de devolver la longitud adecuada para OutputBuffer en el campo Información de estructura IO_STATUS_BLOCK. No solo devuelva directamente la longitud directamente desde una solicitud READ. Por ejemplo, considere una situación en la que los datos devueltos del espacio de usuario indican que hay un búfer 4K. Si el controlador en realidad solo debería devolver 200 bytes, pero en lugar de eso devuelve 4K en el campo Información, se ha producido una vulnerabilidad de divulgación de información. Este problema se produce porque en versiones anteriores de Windows, el búfer que utiliza el Administrador de E/S para la E/S almacenada en búfer no se inicializa a cero. Por lo tanto, la aplicación de usuario recupera los 200 bytes de datos originales más 4K-200 bytes de lo que había en el búfer (contenido del grupo no paginado). Este escenario puede producirse con todos los usos de E/S almacenados en búfer y no solo con IOCTL.

Errores en la E/S directa de IOCTL

Maneje correctamente los búferes de longitud cero. Para obtener más información, consulte Errores en E/S directa.

Errores al hacer referencia a direcciones de espacio de usuario

Lecturas y escrituras de registros específicos del modelo MSR

Los intrínsecos del compilador, como __readmsr y __writemsr se pueden usar para acceder a los registros específicos del modelo. Si se requiere este acceso, el conductor siempre debe comprobar que el registro que se va a leer o escribir esté restringido al índice o rango esperados.

Para obtener más información y ejemplos de código, consulte Proporcionar la capacidad de lectura y escritura de MSR en Procedimientos recomendados para restringir el comportamiento con privilegios elevados en los controladores del modo kernel.

Vulnerabilidades de TOCTOU

Existe una posible vulnerabilidad de tiempo de verificación a tiempo de uso (TOCTOU) cuando se usa E/S directa (para IOCTL o para lectura y escritura). Tenga en cuenta que el controlador accede al búfer de datos de usuario, el usuario puede acceder simultáneamente a él.

Para administrar este riesgo, copie los parámetros que necesiten validarse desde el búfer de datos de usuario a la memoria que sea accesible únicamente desde el modo kernel (como la pila o el grupo). Después, una vez que la aplicación de usuario no pueda acceder a los datos, valide y, a continuación, trabaje con los datos que fueron proporcionados.

El código del controlador debe hacer un uso correcto de la memoria

  • Todas las asignaciones del grupo de controladores deben estar en un grupo que no sea ejecutable (NX). El uso de grupos de memoria NX es intrínsecamente más seguro que el uso de grupos ejecutables no paginados (NP) y proporciona una mejor protección contra ataques de desbordamiento.

  • Los controladores de dispositivo deben manejar correctamente diversas solicitudes en modo usuario, así como solicitudes de E/S de kernel a kernel.

Para permitir que los controladores admitan la virtualización de HVCI, hay requisitos de memoria adicionales. Para obtener más información, consulte Implementación de código compatible con HVCI más adelante en este artículo.

Asas

Objetos de dispositivo

IRP

WDF e IRP

Una ventaja de usar WDF es que los controladores WDF normalmente no acceden directamente a los IRP. Por ejemplo, el marco convierte los IRP de WDM que representan operaciones de control de E/S de lectura, escritura y dispositivo a objetos de solicitud de marco que KMDF/UMDF reciben en colas de E/S.

Si va a escribir un controlador WDM, revise las instrucciones siguientes.

Administrar correctamente los búferes de E/S de IRP

En los artículos siguientes se proporciona información sobre cómo validar los valores de entrada de IRP:

DispatchReadWrite mediante E/S almacenadas en búfer

Errores en E/S almacenada en búfer

DispatchReadWrite mediante E/S directa

Errores en E/S directa

Los Problemas de Seguridad de los Códigos de Control de E/S

Considere la posibilidad de validar los valores asociados a un IRP, como las direcciones y las longitudes del búfer.

Si elige usar Neither E/S, tenga en cuenta que, a diferencia de Lectura y Escritura, y a diferencia de E/S Almacenada en Búfer y E/S Directa, cuando se utiliza Neither E/S IOCTL, el Administrador de E/S no valida los punteros y longitudes del búfer.

Control correcto de las operaciones de finalización de IRP

Un controlador nunca debe completar un IRP con un valor de estado de STATUS_SUCCESS a menos que realmente admita y procese el IRP. Para obtener información sobre las formas correctas de controlar las operaciones de finalización de IRP, consulte Finalización de IRP.

Administración del estado pendiente del IRP del controlador

El controlador debe marcar el IRP como pendiente antes de almacenarlo y debe asegurarse de incluir tanto la llamada a IoMarkIrpPending como la asignación como parte de una secuencia interbloqueada. Para obtener más información, consulte Error al comprobar el estado de un controlador y Retener los IRP entrantes cuando un dispositivo está en pausa.

Manejar las operaciones de cancelación de IRP adecuadamente

Las operaciones de cancelación pueden ser difíciles de codificar correctamente porque normalmente se ejecutan de forma asincrónica. Los problemas en el código que controla las operaciones de cancelación pueden pasar desapercibidos durante mucho tiempo, ya que este código normalmente no se ejecuta con frecuencia en un sistema en ejecución. Asegúrese de leer y comprender toda la información proporcionada en Cancelación de IRP. Preste especial atención a la sincronización de la cancelación de IRP y a los puntos a tener en cuenta al cancelar IRP.

Una forma recomendada de minimizar los problemas de sincronización asociados con las operaciones de cancelación es implementar una cola IRP segura para la cancelación.

Control correcto de las operaciones de limpieza y cierre de IRP

Asegúrese de que comprende la diferencia entre las solicitudes IRP_MJ_CLEANUP y IRP_MJ_CLOSE. Las solicitudes de limpieza llegan después de que una aplicación cierre todos los identificadores de un objeto de archivo, pero a veces antes de que se hayan completado todas las solicitudes de E/S. Las solicitudes de cierre llegan después de que se hayan completado o cancelado todas las solicitudes de E/S para el objeto de archivo. Para obtener más información, consulte los artículos siguientes:

Rutinas DispatchCreate, DispatchClose y DispatchCreateClose

Rutinas DispatchCleanup

Errores en el Control de las Operaciones de Limpieza y Cierre

Para obtener más información sobre el control correcto de IRP, consulte Errores adicionales en el control de IRP.

Otros problemas de seguridad

  • Use un bloqueo o una secuencia entrelazada para evitar condiciones de carrera. Para obtener más información, vea errores de en un entorno multiprocesador.

  • Asegúrese de que los controladores de dispositivo controlan correctamente varios modos de usuario, así como el kernel a las solicitudes de E/S del kernel.

  • Asegúrese de que ni el controlador ni los paquetes de software asociados instalen filtros TDI o LSP durante la instalación o el uso.

Uso de funciones seguras

Vulnerabilidades de código adicionales

Además de las posibles vulnerabilidades que se describen aquí, este artículo proporciona información adicional sobre cómo mejorar la seguridad del código de controlador en modo kernel: Creación de controladores fiables Kernel-Mode.

Para obtener más información sobre la codificación segura de C y C++, consulte Recursos de codificación seguros al final de este artículo.

Administrar el control de acceso del controlador

Elemento de la lista de comprobación de seguridad n.º 7:revise el controlador para asegurarse de que controla el acceso correctamente.

Administración del control de acceso del controlador: WDF

Los controladores deben funcionar para evitar que los usuarios accedan de forma inapropiada a los dispositivos y archivos de un equipo. Para evitar el acceso no autorizado a dispositivos y archivos, debe:

  • Asigne un nombre a los objetos de dispositivo solo cuando sea necesario. Los objetos de dispositivo con nombre generalmente solo son necesarios por motivos heredados, por ejemplo, si tiene una aplicación que espera abrir el dispositivo con un nombre en particular o si está utilizando un dispositivo que no sea PNP o un dispositivo de control. Tenga en cuenta que los controladores WDF no necesitan asignar un nombre FDO al dispositivo PnP para crear un vínculo simbólico mediante WdfDeviceCreateSymbolicLink.

  • Proteger el acceso a los objetos e interfaces del dispositivo.

Para permitir que las aplicaciones u otros controladores WDF accedan al PDO del dispositivo PnP, debe usar interfaces de dispositivo. Para obtener más información, consulte Uso de interfaces de dispositivos. Una interfaz de dispositivo actúa como un vínculo simbólico al PDO de la pila de dispositivos.

Una de las mejores formas de controlar el acceso al PDO es especificando una cadena SDDL en el INF. Si la cadena SDDL no está en el archivo INF, Windows aplicará un descriptor de seguridad predeterminado. Para obtener más información, consulte Protección de objetos de dispositivo y SDDL para objetos de dispositivo.

Para obtener más información sobre el control del acceso, consulte los siguientes artículos:

Control del acceso a dispositivos en controladores KMDF

Nombres, descriptores de seguridad y clases de dispositivo: hacer que los objetos de dispositivo sean accesibles... and SAFE desde enero, febrero 2017 The NT Insider Newsletter publicado por OSR.

Administración del control de acceso del controlador: WDM

Si está trabajando con un controlador WDM y ha usado un objeto de dispositivo con nombre, puede usar IoCreateDeviceSecure y especificar un SDDL para protegerlo. Al implementar IoCreateDeviceSecure, especifique siempre un GUID de clase personalizado para DeviceClassGuid. No debe especificar aquí un GUID de clase existente. Si lo hace, puede interrumpir la configuración de seguridad o la compatibilidad con otros dispositivos que pertenecen a esa clase. Para obtener más información, vea WdmlibIoCreateDeviceSecure.

Para obtener más información, consulte los artículos siguientes:

Control del acceso al dispositivo

Control del acceso al espacio de nombres del dispositivo

modelo de seguridad de Windows para desarrolladores de controladores

Jerarquía de riesgos de identificadores de seguridad (SID)

En la sección siguiente se describe la jerarquía de riesgos de los SID comunes que se usan en el código de controlador. Para obtener información general sobre SDDL, consulte SDDL para objetos de dispositivo, Cadenas SID y la sintaxis de cadenas SDDL.

Es importante comprender que si se permite que los autores de llamadas con privilegios inferiores accedan al kernel, se aumenta el riesgo de código. En este diagrama de resumen, el riesgo aumenta a medida que se permite el acceso de los SIDs de menor privilegio a la funcionalidad de su controlador.

SY (System)
\/
BA (Built-in Administrators)
\/
LS (Local Service)
\/
BU (Built-in User)
\/
AC (Application Container)

Después del principio general de seguridad de privilegios mínimos, configure solo el nivel mínimo de acceso necesario para que el controlador funcione.

Control de seguridad IOCTL pormenorizado de WDM

Para administrar aún más la seguridad cuando los autores de llamadas en modo de usuario envían IOCTL, el código de controlador puede incluir la función IoValidateDeviceIoControlAccess. Esta función permite a un controlador comprobar los derechos de acceso. Al recibir un IOCTL, un controlador puede llamar a IoValidateDeviceIoControlAccess, especificando FILE_READ_ACCESS, FILE_WRITE_ACCESS o ambos.

La implementación de un control de seguridad IOCTL pormenorizado no reemplaza la necesidad de administrar el acceso de los controladores mediante las técnicas descritas anteriormente.

Para obtener más información, consulte los artículos siguientes:

Definir Códigos de Control de E/S

Implementación de código compatible con HVCI

elemento de lista de comprobación de seguridad n.º 8:Validar que el controlador usa memoria para que sea compatible con HVCI.

Uso de memoria y compatibilidad con HVCI

HVCI usa tecnología de hardware y virtualización para aislar la función de toma de decisiones de integridad de código (CI) del resto del sistema operativo. Cuando se utiliza la seguridad basada en virtualización para aislar CI, la única forma en que la memoria del kernel se puede convertir en ejecutable es mediante una verificación de CI. Esto significa que las páginas de memoria del kernel nunca pueden ser grabables y ejecutables (W+X) y el código ejecutable no se puede modificar directamente.

Para implementar código compatible con HVCI, asegúrese de que el código de controlador haga lo siguiente:

  • Participa en NX de forma predeterminada
  • Usa las API o marcas de NX para la asignación de memoria (NonPagedPoolNx)
  • No usa secciones que son grabables y ejecutables
  • No intenta modificar directamente la memoria del sistema ejecutable
  • No usa código dinámico en kernel
  • No carga archivos de datos como ejecutables
  • La alineación de sección es un múltiplo de 0x1000 (PAGE_SIZE). Por ejemplo, DRIVER_ALIGNMENT=0x1000

Para obtener más información sobre el uso de la herramienta y una lista de llamadas a memoria incompatibles, consulte Implementación de código compatible con HVCI.

Para obtener más información sobre la prueba de seguridad de los aspectos básicos del sistema relacionados, consulte Prueba de preparación de integridad de código de HyperVisor e Integridad del código protegido por hipervisor (HVCI).

Seguir prácticas recomendadas de codificación específicas para la tecnología

Elemento de la lista de comprobación de seguridad n.º 9:revise la siguiente guía tecnológica específica para el controlador.

Sistemas de archivos

Para obtener más información, acerca de la seguridad del controlador del sistema de archivos, consulte los artículos siguientes:

Introducción a la seguridad de los sistemas de archivos

problemas de seguridad del sistema de archivos

Características de seguridad para sistemas de archivos

Coexistencia con otros controladores de filtro del sistema de archivos

NDIS: redes

Para obtener información sobre la seguridad del controlador NDIS, consulte Cuestiones de Seguridad para Controladores de Red.

Display

Para obtener información sobre la seguridad del controlador de visualización, consulte <Contenido pendiente>.

Impresoras

Para obtener información relacionada con la seguridad del controlador de impresora, consulte Consideraciones de seguridad del controlador de impresora V4.

Problemas de seguridad para controladores de adquisición de imágenes de Windows (WIA)

Para obtener información sobre la seguridad de WIA, consulta Problemas de seguridad de los controladores WIA de adquisición de imágenes de Windows.

Mejora de la seguridad de la instalación de dispositivos

Elemento de la lista de comprobación de seguridad n.º 10:revise las instrucciones de creación e instalación del controlador para asegurarse de que sigue los procedimientos recomendados.

Al crear el código que instala el controlador, debe asegurarse de que la instalación del dispositivo siempre se realizará de forma segura. Una instalación segura de dispositivos es una que hace lo siguiente:

  • Limita el acceso al dispositivo y a sus clases de interfaz de dispositivo.
  • Limita el acceso a los servicios de controlador que se crearon para el dispositivo.
  • Protege los archivos de controlador de la modificación o eliminación
  • Limita el acceso a las entradas del Registro del dispositivo.
  • Limita el acceso a las clases WMI del dispositivo.
  • Usa las funciones SetupAPI correctamente

Para obtener más información, consulte los artículos siguientes:

Creación de Instalaciones Seguras de Dispositivos

Directrices para el uso de setupAPI

Uso de funciones de instalación de dispositivos

Temas avanzados de instalación de dispositivos y controladores

Realizar una revisión del código del mismo nivel

elemento de lista de comprobación de seguridad n.º 11:Realizar revisión del código del mismo nivel, para buscar problemas no expuestos por las otras herramientas y procesos

Busque revisores de código con conocimientos para buscar problemas que puede haber perdido. Un segundo conjunto de ojos a menudo verá problemas que puede haber pasado por alto.

Si no tiene personal adecuado para revisar el código internamente, considere contratar ayuda externa para este propósito.

Ejecutar la firma adecuada del controlador de versión

Elemento de la lista de comprobación de seguridad n.º 12:use el portal de asociados de Windows para firmar correctamente el controlador para su distribución.

Antes de liberar un paquete de controladores al público, se recomienda enviar el paquete para su certificación. Para obtener más información, consulte Prueba de rendimiento y compatibilidad, Introducción al programa de Hardware, Servicios del Panel de Control de Hardwarey firma de atestación de un controlador de kernel para la versión pública.

Uso de CodeQL para comprobar el código del controlador

Elemento de la lista de comprobación de seguridad n.º 13:use CodeQL para comprobar si hay vulnerabilidades en el código de controlador.

CodeQL, de GitHub, es un motor de análisis de código semántico y la combinación de un amplio conjunto de consultas de seguridad junto con una plataforma sólida lo convierten en una herramienta inestimable para proteger el código de controlador. Para obtener más información, consulte CodeQL y Static Tools Logo Test.

Añade anotaciones SAL a tu código de controlador

Elemento de la lista de comprobación de seguridad n.º 14:agregue anotaciones SAL a en el código de controlador.

El lenguaje de anotación de código fuente (SAL) proporciona un conjunto de anotaciones que puede usar para describir cómo una función usa sus parámetros, las suposiciones que realiza sobre ellos y las garantías que realiza cuando finaliza. Las anotaciones se definen en el archivo de encabezado sal.h. El análisis de código de Visual Studio para C++ usa anotaciones SAL para modificar su análisis de funciones. Para obtener más información sobre el desarrollo de controladores SAL 2.0 para Windows, consulta Anotaciones de SAL 2.0 para controladores de Windows y Usar anotaciones SAL para reducir defectos de código de C/C++.

Para obtener información general sobre SAL, consulte este artículo disponible en OSR. https://www.osr.com/blog/2015/02/23/sal-annotations-dont-hate-im-beautiful/

Uso del comprobador de controladores para comprobar si hay vulnerabilidades

elemento de lista de comprobación de seguridad n.º 15:Usar comprobador de controladores para comprobar si hay vulnerabilidades en el código de controlador.

El Comprobador de controladores usa un conjunto de reglas de interfaz y un modelo del sistema operativo para determinar si el controlador interactúa correctamente con el sistema operativo Windows. DV encuentra defectos en el código de controlador que podrían apuntar a posibles errores en los controladores.

El Comprobador de controladores permite realizar pruebas en vivo del controlador. El comprobador de controladores supervisa los controladores del modo kernel de Windows y los controladores de gráficos para detectar llamadas o acciones de función no válidas que podrían dañar el sistema. El Comprobador de controladores puede someter los controladores de Windows a una variedad de tensiones y pruebas para encontrar un comportamiento incorrecto. Para obtener más información, consulte Comprobador de controladores.

Tenga en cuenta que solo ciertos tipos de controladores son compatibles con DV. Para obtener más información sobre los controladores que DV puede comprobar, consulte controladores compatibles. Consulte las páginas siguientes para obtener información sobre las pruebas DV disponibles para el tipo de controlador con el que está trabajando.

Para familiarizarse con DV, puede usar uno de los controladores de ejemplo (por ejemplo, el ejemplo de toaster destacado: https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured).

Comprobación del código con el Analizador binario binSkim

elemento de lista de comprobación de seguridad n.º 16:Siga estos pasos para usar BinSkim para comprobar que las opciones de compilación y compilación están configuradas para minimizar los problemas de seguridad conocidos.

Use BinSkim para examinar los archivos binarios para identificar las prácticas de codificación y creación que pueden representar potencialmente la vulnerabilidad binaria.

BinSkim comprueba si:

  • Uso de conjuntos de herramientas del compilador obsoletos: los archivos binarios deben compilarse en los conjuntos de herramientas del compilador más recientes siempre que sea posible para maximizar el uso de mitigaciones de seguridad proporcionadas por el compilador y del sistema operativo actuales.
  • Configuración de compilación no segura: los archivos binarios deben compilarse con la configuración más segura posible para habilitar mitigaciones de seguridad proporcionadas por el sistema operativo, maximizar los errores del compilador y los informes de advertencias accionables, entre otras cosas.
  • Problemas de firma: los archivos binarios firmados deben firmarse con algoritmos criptográficos seguros.

BinSkim es una herramienta de código abierto y genera archivos de salida que usan el formato de intercambio de resultados de análisis estáticos (formato SARIF). BinSkim reemplaza la herramienta anterior BinScope.

Para obtener más información sobre BinSkim, consulte Usar BinSkim para comprobar los binarios y la Guía del Usuario de BinSkim.

Comprobación del código con las pruebas del programa de compatibilidad de hardware

elemento de lista de comprobación de seguridad n.º 17:Use las pruebas del programa de compatibilidad de hardware relacionadas con la seguridad para comprobar si hay problemas de seguridad.

El programa de compatibilidad de hardware incluye pruebas relacionadas con la seguridad se puede usar para buscar vulnerabilidades de código. El Programa de compatibilidad de hardware de Windows aprovecha las pruebas del Kit de laboratorio de hardware de Windows (HLK). Las pruebas de aspectos básicos del dispositivo HLK se pueden usar en la línea de comandos para ejercer el código del controlador y sondear si hay puntos débiles. Para obtener información general sobre las pruebas fundamentales del dispositivo y el programa de compatibilidad de hardware, consulte Windows Hardware Lab Kit.

Las siguientes pruebas son ejemplos de pruebas que pueden resultar útiles para comprobar el código de controlador para ver algunos comportamientos asociados a vulnerabilidades de código:

DF: Prueba aproximada de IOCTL aleatoria (confiabilidad)

DF: Prueba aproximada de aperturas relativas (confiabilidad)

DF: Prueba aproximada FSCTL de búfer de longitud cero (confiabilidad)

DF: Prueba aproximada de FSCTL aleatoria (confiabilidad)

DF: Prueba aproximada de Misc API (confiabilidad)

También puede usar la pruebas de vulnerabilidad ante datos aleatorios o inesperados de demora en la sincronización del kernel que se incluye con el comprobador de controladores.

Las pruebas CHAOS (hardware simultáneo y sistema operativo) ejecutan varias pruebas de controladores PnP, pruebas aproximadas del controlador de dispositivo y pruebas del sistema de energía simultáneamente. Para obtener más información, consulte Pruebas CHAOS (aspectos básicos del dispositivo).

Las pruebas de penetración de los fundamentos del dispositivo realizan varias formas de ataques de entrada, que son un componente crítico de las pruebas de seguridad. Las pruebas de ataque y penetración pueden ayudar a identificar vulnerabilidades en las interfaces de software. Para obtener más información, consulte Pruebas de penetración (aspectos básicos del dispositivo).

Utilice el Device Guard: Prueba de Cumplimiento, junto con las otras herramientas descritas en este artículo, para confirmar que su controlador es compatible con HVCI.

Herramientas de prueba personalizadas y específicas del dominio

Considere el desarrollo de pruebas de seguridad específicas del dominio personalizadas. Para desarrollar pruebas adicionales, recopile información de los diseñadores originales del software, así como de recursos de desarrollo externos familiarizados con el controlador específico que se está desarrollando y de una o más personas que conozcan el análisis y la prevención de intrusiones de seguridad.

Comprender cómo se notifican los controladores mediante el Centro de informes de controladores vulnerables y malintencionados de Microsoft

Elemento de lista de comprobación de seguridad n.º 18: comprenda cómo se notifican los controladores mediante el Centro de informes de controladores vulnerables y malintencionados de Microsoft

Cualquier persona puede enviar un controlador interrogable mediante el Centro de informes de controladores vulnerables y malintencionados de Microsoft. Consulte esta entrada de blog para obtener información sobre cómo se envían los controladores para su análisis: Mejorar la seguridad del kernel con el nuevo Centro de informes de controladores vulnerables y malintencionados de Microsoft

El Centro de informes puede examinar y analizar controladores de Windows creados para arquitecturas x86 y x64. Los controladores analizados vulnerables y malintencionados se marcan para su análisis e investigación por parte del equipo de controladores vulnerables de Microsoft. Una vez confirmados los controladores vulnerables, se emite una notificación adecuada y se añaden a la lista de bloqueos de controladores vulnerables. Para obtener más información sobre esto, consulte reglas de bloqueo de controladores recomendadas por Microsoft. Estas reglas se aplican de forma predeterminada a los dispositivos habilitados para integridad de código protegido por hipervisor (HVCI) y Windows 10 en modo S.

Revisión de los recursos de codificación seguros

Elemento de la lista de comprobación de seguridad n.º 19:revise estos recursos para ampliar la comprensión de los procedimientos recomendados de codificación segura aplicables a los desarrolladores de controladores.

Directrices de codificación de controladores en modo kernel seguro

Crear controladores fiables Kernel-Mode

Protección de las organizaciones de codificación

Carnegie Mellon University SEI CERT

Estándar de codificación C De la Universidad Carnegie Mellon: Reglas para desarrollar sistemas seguros, confiables y seguros (edición 2016).

MITRE - Debilidades Abordadas por el Estándar de Codificación Segura CERT C

Creación de seguridad en el modelo de madurez (BSIMM): https://www.bsimm.com/

SAFECode: https://safecode.org/

Recursos CISA

OSR

OSR proporciona servicios de consultoría y aprendizaje para el desarrollo de controladores. Estos artículos del boletín OSR destacan los problemas de seguridad de los controladores.

Nombres, descriptores de seguridad y clases de dispositivo: hacer que los objetos de dispositivo sean accesibles... and SAFE

Debe usar la protección: seguridad interna del controlador & del dispositivo

Bloqueo de controladores: una encuesta sobre técnicas

Meltdown y Spectre: ¿qué pasa con los controladores?

Estudio de casos

De alerta a vulnerabilidad del controlador: la investigación de ATP de Microsoft Defender descubre el error de elevación de privilegios

Libros

24 pecados mortales de seguridad de software: errores de programación y cómo corregirlos por Michael Howard, David LeBlanc y John Viega

el arte de la evaluación de seguridad de software: identificación y prevención de vulnerabilidades de software, Mark Dowd, John McDonald y Justin Schuh

Escribir Software Seguro Segunda Edición, de Michael Howard y David LeBlanc

The Art of Software Security Assessment: Identificación y prevención de vulnerabilidades de software, Mark Dowd y John McDonald

codificación segura en C y C++ (serie SEI en ingeniería de software) 2ª edición, Robert C. Seacord

Programar el Modelo de Controlador de Microsoft Windows (2ª Edición), Walter Oney

Desarrollar controladores con Windows Driver Foundation (Referencia del desarrollador), Penny Orwick y Guy Smith

Adiestramiento

El entrenamiento educativo de controladores de Windows está disponible en proveedores como los siguientes:

El entrenamiento en línea de codificación segura está disponible desde una variedad de orígenes. Por ejemplo, este curso está disponible en coursera en:

Identificar vulnerabilidades de seguridad en la programación de C/C++.

SAFECode también ofrece entrenamiento gratuito:

SAFECode.org/training

Certificación profesional

CERT ofrece una certificación de Profesional en Codificación Segura .

Resumen de las conclusiones clave

La seguridad del conductor es una tarea compleja que contiene muchos elementos, pero estos son algunos puntos clave que se deben tener en cuenta:

  • Los controladores residen en el kernel de Windows y tener un problema cuando se ejecutan en el kernel expone todo el sistema operativo. Por este motivo, preste mucha atención a la seguridad y al diseño de los controladores teniendo en cuenta la seguridad.

  • Aplique el principio de privilegios mínimos:

    a. Usar una cadena SDDL estricta para restringir el acceso al controlador

    b. Restringir aún más los IOCTL individuales

  • Cree un modelo de amenazas para identificar vectores de ataque y considere si algo se puede restringir más.

  • Tenga cuidado con los punteros incrustados que se pasan desde el modo de usuario. Es necesario probarlos, acceder a ellos dentro de try except y son propensos a vulnerabilidad de tiempo de verificación a tiempo de uso (ToCToU) a menos que se capture y compare el valor del búfer.

  • Si no está seguro, use METHOD_BUFFERED como método de almacenamiento en búfer IOCTL.

  • Use utilidades de análisis de código para buscar vulnerabilidades de código conocidas y corregir los problemas identificados.

  • Busque revisores de código con conocimientos para buscar problemas que puede haber perdido.

  • Use comprobadores de controladores y pruebe el controlador con varias entradas, incluidos casos extremos.