Vulnerabilidades de la pila TCP/IP de FreeRTOS: los detalles

Investigador: Ori Karliner (@orihcx) Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Siguiendo nuestro Blog desde el mes pasado, este blog cubrirá los detalles técnicos de nuestros hallazgos.

Si sospecha que alguno de sus dispositivos está afectado por estas vulnerabilidades y desea nuestra evaluación, contáctenos en [email protected]

Información general

Antes de sumergirnos en las vulnerabilidades, hay algunas cosas importantes a tener en cuenta.

La pila FreeRTOS+TCP TCP/IP es altamente configurable. Algunas de las vulnerabilidades solo existen para configuraciones específicas.

Todos los paquetes se almacenan utilizando la estructura NetworkBufferDescriptor_t:

1672323759 51 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

FreeRTOS+TCP ofrece dos esquemas de asignación para almacenar los paquetes:

  1. BufferAllocation_1.c: el controlador de red asigna estáticamente todos los búfer de paquetes en tiempo de compilación, al tamaño máximo que puede tener un paquete (ipTOTAL_ETHERNET_FRAME_SIZE).
  2. BufferAllocation_2.c: los búferes de paquetes se asignan dinámicamente desde el montón según el tamaño necesario. Los búferes de paquetes tienen un tamaño mínimo: baMINIMAL_BUFFER_SIZE. Este tamaño depende de la configuración de la pila TCP/IP, pero es del tamaño de un paquete TCP o de un paquete ARP.

Además, en algunas implementaciones, el controlador de red puede asignar el búfer de paquetes de una manera diferente. En ese caso, el impacto de las vulnerabilidades diferirá en consecuencia.

Según el esquema de configuración y asignación que se utilice, algunas de las vulnerabilidades pueden tener diferentes niveles de impacto.

Recomiendo leer el código fuente junto con esta divulgación para comprender completamente las vulnerabilidades y si están presentes o no en su configuración de FreeRTOS+TCP.

CVE-2018-16528 – Módulos de conectividad segura de AWS – corrupción de contexto mbedTLS

El agente MQTT y los módulos GGD hacen un mal uso de la API de mbedTLS, creando un objeto de contexto mbedTLS corrupto. El objeto corrupto puede conducir a la ejecución remota de código.

Los módulos de descubrimiento de MQTT y Greengrass son vulnerables en diferentes flujos de código.

Para esta divulgación, me centraré en el flujo en el que un agente MQTT se conecta a un corredor: prvSetupConnection.

La función configura la conexión TLS a un servidor certificado.

Inicializa el socket, configura los parámetros TLS y luego se conecta al servidor:

1672323759 336 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

SOCKETS_Conectar llamadas internas TLS_Conectarque envuelve la biblioteca mbedTLS:

1672323759 491 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Se repite hasta que se realiza el protocolo de enlace TLS o hasta que se produce un error.

De regreso prvSetupConnectionpodemos ver que si SOCKETS_Conectar falla, prvGracefulSocketCerrar se llama.

Esta función limpia internamente la conexión y cierra el socket:

1672323760 498 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Primero recibe los datos que quedan en el socket y luego lo cierra.

SOCKETS_Recv una vez más envuelve TLS_Recvque envuelve mbedTLS:

1672323760 346 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Este flujo es muy problemático, ya que SOCKETS_Conectar podría haber fallado porque el protocolo de enlace TLS falló, y ahora estamos usando el mismo contexto mbedTLS (pCtx->mbedSslCtx) para leer datos (mbedtls_ssl_read).

mbedtls_ssl_handshake podría haber dejado el contexto TLS en un estado corrupto, y los comentarios sobre la API mbedTLS advierten explícitamente a los usuarios sobre este escenario:

1672323761 20 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Hemos encontrado un flujo de código dentro de mbedTLS que hará que un búfer de almacenamiento dinámico se libere dos veces debido a este mal uso de la API, pero no lo cubriremos en esta divulgación.

Impacto

Un atacante puede lograr la ejecución remota de código.

CVE-2018-16522: módulos de conectividad segura de AWS: sin puntero no inicializado

Él SOCKETS_SetSockOpt La función del módulo de sockets seguros de AWS puede hacer que se libere un puntero no inicializado.

La falla solo existe en los casos en que el usuario proporciona una lista de 2 o más protocolos ALPN.

El usuario proporciona una lista de protocolos ALPN y SOCKETS_SetSockOpt guarda una copia de ellos dentro del contexto del socket.

Al principio, el campo de recuento de protocolos se establece de acuerdo con la longitud proporcionada por el usuario:

1672323761 44 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Se asigna una matriz de punteros en el pxContext->ppcAlpnProtocolos campo, cada uno de estos punteros apuntará a un solo nombre de protocolo:

1672323761 9 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Luego, los búferes para cada nombre de protocolo se asignan y se asignan a esta matriz de punteros:

1672323761 179 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

El problema es que el Protocolos ppcAlpn la matriz de punteros no se limpia (memset a 0) después de la asignación, lo que significa que contendrá datos de asignaciones anteriores en el montón.

Como podemos ver, si falla la asignación de un búfer de nombre de protocolo, el código saldrá, pero solo el puntero a ese búfer específico será NULL.

Si tenemos 2 protocolos ALPN y falla la asignación de búfer para el primero, el puntero al segundo permanece sin inicializar, mientras que el ulAlpnProtocolsCount queda en 3.

Más tarde, cuando se cierra el Socket, liberamos este arreglo de punteros:

1672323761 940 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Lo que significa un puntero no inicializado (Protocolos ppcAlpn[1]) será liberado.

Impacto

Combinado con una primitiva de agotamiento de montón, un atacante puede lograr la ejecución remota de código.

CVE-2018-16526 – corrupción de memoria usGenerateProtocolChecksum

El flujo problemático comienza en prvProcessIPPacketmientras analiza las opciones de IP:

1672323762 139 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

1672323762 162 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

El código no maneja las opciones de IP en absoluto y simplemente las elimina del paquete usando memmove y truncando el xDataLength campo del búfer de red.

El problema aquí, es que el pxIPHeader->ucVersionHeaderLength El campo no se actualiza en consecuencia, para representar el nuevo tamaño del encabezado IP.

Este campo también se utiliza cuando se envían paquetes, en usGenerateProtocolChecksum:

1672323762 711 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Esta función se utiliza para generar o comprobar la suma de comprobación del protocolo de la capa superior (TCPUDPICMP…).

Él ucVersionHeaderLength El campo se utiliza para determinar dónde comienza la siguiente capa (pxProtPaquete), de modo que la suma de comprobación calculada se pueda colocar en el desplazamiento correcto de acuerdo con el protocolo utilizado.

Por ejemplo, si el paquete saliente es un paquete TCP:

1672323762 891 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Primero, el campo de suma de verificación es cero:

1672323762 111 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Y luego la suma de verificación calculada se asigna a este campo:

1672323763 497 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

En muchos casos, un paquete Tx se crea sobre el búfer del paquete Rx, o al menos en función de su encabezado IP.

Si el paquete Rx tenía opciones de IP, sabemos que el código ya las había eliminado, pero que no ajustó el xIPHeader->ucVersionHeaderLength campo en consecuencia.

Eso significa que al generar la suma de control del protocolo para el paquete transmitido, pxProtPaquete apuntará al encabezado del protocolo como si las opciones de IP todavía estuvieran allí.

Podemos hacer que la suma de comprobación del protocolo se genere con un desplazamiento de hasta 40 bytes desde su posición real en el paquete, ya que 40 es el tamaño máximo de las opciones de IP.

En los casos en que el búfer del paquete se redujo, o en los casos en que el paquete Tx se basa en el encabezado IP de un paquete Rx anterior, este desplazamiento de 40 bytes puede señalar fuera de los límites del búfer y provocar una corrupción de la memoria.

Hay múltiples flujos de código que se pueden usar para la explotación, pero no los cubriremos en esta divulgación.

Impacto

Un atacante puede filtrar información.

(Solo con BufferAllocation_2.c) Un atacante puede lograr la ejecución remota de código en el dispositivo.

CVE-2018-16525: fuga de información de corrupción de memoria DNSLLMNR

Múltiples errores hacen posible que un atacante corrompa la memoria o filtre información al enviar paquetes DNSLLMNR al dispositivo.

La misma función (ulDNSHandlePacket) se utiliza para analizar las respuestas de consultas de DNS y LLMNR.

El primer error está en el prvProcessIPPacket función, mientras se envía un paquete UDP:

1672323763 310 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Antes de que el paquete UDP se envíe a través de xProcessReceivedUDPPacketla longitud total del paquete (xDataLength) se vuelve a calcular para representar solo el tamaño de la carga útil de UDP.

El error aquí es que no se hace nada para validar que el par suministró una longitud válida en el encabezado UDP (xUDPHader.usLongitud), lo que significa que un atacante puede causar xDataLength ser más pequeño o más grande que la longitud real de la carga útil.

El próximo error está en prvParseDNSReplymientras analiza una solicitud DNSLLMNR.

Generalmente, el código en prvParseDNSReply no hace nada para validar que los datos analizados estén dentro de los límites del paquete recibido.

1672323763 341 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

En caso de que se recibiera una consulta DNS de tipo HOST y clase IN para el nombre de host del dispositivo (xApplicationDNSQueryHook), el código responde a esa solicitud.

En primer lugar, se debe asignar un búfer más grande para la respuesta, ya que la respuesta se adjunta al paquete DNS original:

1672323763 482 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

El código calcula el nuevo tamaño sumando a xDataLength el tamaño de todos los encabezados de paquetes necesarios (UDP, IP, ETH) y el tamaño de la respuesta LLMNR (16), y asigna un nuevo búfer usando pxDuplicateNetworkBufferWithDescriptor.

Como vimos, un atacante puede causar xDataLength ser más pequeño o más grande que el tamaño real de la carga útil. Eso significa que cuando se asigna el búfer de respuesta, puede ser demasiado pequeño para contener el paquete original, o puede ser más grande, lo que provoca pxDuplicateNetworkBufferWithDescriptor para copiar datos fuera de los límites del búfer original al nuevo (datos que luego pueden filtrarse al atacante).

Para comprender las implicaciones de este error, observemos el código que genera la respuesta:

1672323764 424 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Como podemos ver, xDesplazamiento1 se usa para calcular el desplazamiento del final del paquete DNS, donde queremos insertar nuestra respuesta. Luego lo usamos para construir la respuesta LLMNR usando pxRespuesta.

Para el esquema de asignación dinámica de búfer (BufferAllocation_2.c), podemos causar pxDuplicateNetworkBufferWithDescriptor para asignar un búfer que es demasiado pequeño para contener la respuesta.

Eso significa que un atacante puede invadir los datos en un desplazamiento elegido (xDesplazamiento1) del búfer de red asignado, con el LLMNRResponder_t los campos.

Para el esquema de asignación de búfer estático (BufferAllocation_1.c), podemos causar pxDuplicateNetworkBufferWithDescriptor para corromper la memoria fuera del nuevo búfer:

1672323765 687 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Tenemos control total sobre el xDataLength del búfer del paquete original (debido al error del código UDP).

Dado que el búfer tiene un tamaño constante en este esquema de asignación, al proporcionar un xDataLength es más grande que el tamaño del búfer estático, podemos desbordarlo.

Esta vulnerabilidad también se puede utilizar para filtrar información, si un atacante agrega otra consulta de DNS con una longitud truncada al paquete:

1672323765 693 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

El único problema al que se enfrentará un atacante es que usType y usClass ambos no están bajo su control (porque se leen fuera de los límites), y ambos deben ser 1 para que se envíe una respuesta LLMNR.

Esto se puede lograr mediante el uso de algún tipo de forma de montón, y producirá todos los datos entre el búfer de la red y el desplazamiento de datos con forma que se envían de vuelta al atacante.

Impacto

Un atacante puede lograr la ejecución remota de código.

Un atacante puede filtrar información.

CVE-2018-16599 – Fuga de información de corrupción de memoria NBNS

prvTreatNBNSal igual que prvParseDNSReplyno comprueba si xDataLength es lo suficientemente grande como para contener el paquete NBNS analizado, lo que permite que un atacante lea datos fuera de los límites.

Además, al igual que prvParseDNSReply, pxDuplicateNetworkBufferWithDescriptor se utiliza para asignar el paquete Tx, y xDataLength es controlable por el atacante (a través del error de campo de longitud UDP):

1672323765 398 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Eso significa que en el esquema de asignación de búfer estático (Asignación de búfer_1.c)un atacante puede corromper la memoria proporcionando un xDataLength eso es más grande que el tamaño del búfer estático.

Impacto

Un atacante puede filtrar información.

(Solo con BufferAllocation_1.c) Un atacante puede lograr la ejecución remota de código.

CVE-2018-16601 – Daños en la memoria IP DoSMemory

La función prvProcessIPPacket elimina el campo de opciones de IP de un paquete Rx si está presente.

El tamaño de la cabecera IP no se valida en ningún momento:

1672323765 45 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Si un atacante proporciona un campo de longitud de encabezado IP (uxHeaderLength) que es más grande que todo el paquete (pxNetworkBuffer->xDataLength) menos ipSIZE_OF_IPv4_HEADER (20), el cálculo de xMoveLen causará un subdesbordamiento de enteros.

Esto hará que memmove mueva una gran cantidad de datos, cubriendo toda el área de memoria de 32 bits, con un rango muy pequeño para jugar.

Impacto

Un atacante puede causar un DoS.

En algunos casos, un atacante puede lograr la ejecución remota de código.

CVE-2018-16523, CVE-2018-16524 – Información de opciones de TCP fugaDoS

La función prvCheckOptions comprueba las opciones de TCP suministradas dentro de un paquete Rx TCP, si las hay:

1672323766 74 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

El código no valida que el búfer de paquetes sea lo suficientemente grande para contener las opciones de TCP (pxNetworkBuffer->xDataLength):

1672323766 115 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

pucÚltimo no se verifica en absoluto, para ver si encaja dentro del paquete recibido, y el ciclo while que itera las opciones de TCP solo verifica si la opción actual comienza dentro del rango válido (pucPtr pucÚltimo), pero no se hace nada para garantizar que termine dentro del rango válido.

Cada uno de los controladores de opciones TCP puede acceder a datos fuera de los límites y, en algunos casos, un atacante puede recuperar estos datos (filtrando así información).

Él TCP_OPT_MSS handler también contiene una vulnerabilidad DoS:

1672323766 230 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Al volver a calcular el RxWindowLengthsi un atacante proporciona un MSS de 0, esta línea se dividirá por 0, lo que generará una excepción y provocará un DoS.

Impacto

Un atacante puede causar un DoS.

Un atacante puede filtrar información.

CVE-2018-16603 – Fuga de información de TCP

xProcessReceivedTCPPacket no valida que el marco recibido sea lo suficientemente grande como para contener un encabezado TCP. Se puede acceder a los campos del encabezado TCP fuera de los límites:

1672323767 71 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Si un atacante envía un paquete IP con tipo TCP, pero no incluye el encabezado TCP, xPuertoLocal y xPuertoRemoto se leerá fuera de los límites, y un paquete RST que utilice estos puertos se enviará de vuelta con prvTCPSendResetfiltrando así datos al atacante.

Impacto

Un atacante puede filtrar información.

CVE-2018-16602 – Fuga de información de DHCP

Él prvProcessDHCPRespuestas La función no valida que un paquete sea lo suficientemente grande para ser un paquete DHCP válido.

1672323767 851 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Además, al recorrer los campos de opciones de DHCP, las comprobaciones de longitud no se realizan correctamente para las opciones de DHCP:

1672323767 90 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Como no se hace ninguna verificación para ver si pucByte[1] incluso se puede acceder, y pucByte + uclongitud no se comprueba contra pucÚltimoByte.

Al hacer que el código lea algunos parámetros de DHCP fuera de los límites (por ejemplo, la dirección IP ofrecida), un atacante puede observar estos valores más adelante y filtrar información.

Impacto

Un atacante puede filtrar información.

CVE-2018-16600 – Fuga de información ARP

Paquete de proceso eARP no valida que la trama recibida sea lo suficientemente grande para ser un paquete ARP:

1672323767 58 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

Se accede a los campos del paquete ARP sin realizar una verificación de límites adecuada, lo que significa que se puede acceder a los datos fuera de los límites.

Un atacante puede filtrar información al observar las respuestas de los paquetes ARP truncados.

Impacto

Un atacante puede filtrar información.

CVE-2018-16527 – Fuga de información ICMP

prvProcessICMPPacket no valida que la trama recibida sea lo suficientemente grande para ser un paquete ICMP y puede acceder a los campos de este paquete fuera de los límites:

1672323768 484 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

El atacante puede filtrar información al observar la respuesta a una solicitud de eco ICMP truncada.

Impacto

Un atacante puede filtrar información.

CVE-2018-16598 – Envenenamiento por DNS

El código no toma medidas para evitar el envenenamiento de DNS, ya que cualquier respuesta de DNS que reciba el dispositivo se analizará por completo, sin verificar si coincide con una consulta de DNS saliente.

Podemos ver que en la función xProcessReceivedUDPPacket:

1672323768 902 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

ulDNSHandlePacket simplemente envuelve prvParseDNSReply.

1672323768 706 Vulnerabilidades de la pila TCPIP de FreeRTOS los detalles

prvParseDNSReply analizará la respuesta de DNS y actualizará la caché de DNS en consecuencia:

Impacto

Un atacante puede envenenar la caché de DNS del dispositivo.

1669383135 916 Dont Give Me a Brake Xiaomi Scooter Hack permite aceleraciones

Deja un comentario