
CVE-2020-16899 - Lógica de detección y regla de vulnerabilidad TCP/IP de Microsoft Windows
El 13 de octubre, Microsoft anunció una vulnerabilidad crítica en la pila IPv6 de Windows que permite a un atacante enviar paquetes maliciosamente diseñados que provocan un BSOD (Pantalla Azul de la Muerte) inmediato en las versiones más recientes de Windows 10 y Windows Server 2019. Aunque esta vulnerabilidad no parece otorgar ejecución de código a un atacante, podría utilizarse para ataques masivos de denegación de servicio contra versiones vulnerables de Windows. La lógica de detección para la versión de RCE más impactante de esta vulnerabilidad se encuentra en CVE-2020-16898: "Bad Neighbor".
Este documento ha sido preparado por McAfee Advanced Threat Research. Su objetivo es proporcionar información valiosa para administradores de redes y personal de seguridad que deseen comprender mejor esta vulnerabilidad y defenderse contra la explotación. La firma aquí presentada debe considerarse y probarse minuciosamente en entornos de prueba antes de ser utilizada en producción, y puede beneficiarse de un ajuste específico para el despliegue objetivo.
La información aquí proporcionada está sujeta a cambios sin previo aviso, y se ofrece "TAL CUAL", con todos los defectos, sin garantía ni aseguramiento sobre la exactitud o aplicabilidad de la información a cualquier situación o circunstancia específica, y se utiliza bajo su propio riesgo. Además, no podemos garantizar ningún rendimiento o eficacia de las firmas.
La vulnerabilidad es el resultado de una lectura fuera de los límites que puede ocurrir cuando la pila IPv6 de Windows procesa paquetes ICMPv6 de Anuncio de Enrutador (Tipo = 134) que contienen uno o más registros de Opción DNSSL (Tipo de Opción = 31). El propósito del registro DNSSL es proporcionar una lista de búsqueda de sufijos de nombres DNS, que se encuentran en su último campo. Dado que esta Lista de Búsqueda puede contener varios nombres DNS terminados en nulo consecutivos, el campo (y por lo tanto todo el registro) puede variar ampliamente en tamaño. Para acomodar esto, el registro de Opción DNSSL contiene su propio campo de Longitud. Sin embargo, dado que la Longitud se cuenta en incrementos de 8 bytes, al menos uno de los nombres de dominio en la Lista de Búsqueda puede tener relleno de nulos adicional para preservar la alineación de 8 bytes del registro. Es en el procesamiento de estos nulos donde se encuentra la vulnerabilidad.
Para cada nombre de dominio en la Lista de Búsqueda, la pila IPv6 de Windows asigna un búfer de 256 bytes. Dado que RFC 1035 limita los nombres de dominio a 255 bytes, esto normalmente sería suficiente para contener un nombre de dominio más su terminador nulo. Sin embargo, el código responsable de consumir los nulos al final de cada nombre de dominio tiene un límite superior igual a los bytes restantes en la Opción, que puede exceder los 256 bytes. El resultado es que el código de consumo de nulos puede consumir incorrectamente más bytes de los asignados para el búfer, causando una lectura fuera de los límites. En el caso de que el búfer se encuentre al final de una página de memoria, esta lectura fuera de los límites puede provocar un BSOD.
La firma de Suricata para esta vulnerabilidad se encuentra en cve-2020-16899.rules y contiene la siguiente lógica:
alert icmp any any -> any any (msg:"Potential CVE-2020-16899 Exploit"; lua:cve-2020-16899.lua; sid:202016899; rev:1;)
El script Lua correspondiente puede encontrarse en cve-2020-16899.lua. Contiene la lógica necesaria para analizar correctamente la capa ICMPv6 e identificar una posible explotación de CVE-2020-16899, de la siguiente manera:
Una vez que localizamos el inicio de la capa ICMPv6, probamos el primer byte de la capa para asegurarnos de que sea un paquete ICMPv6 de Anuncio de Enrutador; si no lo es, salimos.
Dado que las primitivas de Suricata no se han actualizado para analizar las Opciones ICMPv6, simplemente saltamos al byte 17 de la capa ICMPv6, ya que ahí es donde deberían comenzar las Opciones, si están presentes (los primeros 16 bytes son campos de longitud fija, según RFC 4443). Desde allí, recorremos cada Opción hasta que se acaben los bytes del paquete. Para cada Opción, comenzamos inspeccionando el primer byte, que corresponde al campo Tipo de Opción. Mientras ignoramos todas las Opciones que no sean DNSSL, para el Tipo de Opción = 31 (DNSSL), verificamos si la Longitud (segundo byte en la Opción) es mayor o igual a 35, la longitud mínima necesaria para desencadenar la vulnerabilidad: