Serious Security: GnuTLS sigue OpenSSL, corrige el error de ataque de tiempo

Serious Security: GnuTLS sigue OpenSSL, corrige el error de ataque de tiempo

Nodo de origen: 1956368

La semana pasada, escribimos sobre un montón de errores de gestión de memoria que se corrigieron en la última actualización de seguridad de la popular biblioteca de cifrado OpenSSL.

Junto con esos errores de memoria, también informamos sobre un error denominado CVE-2022-4304: Temporización de Oracle en el descifrado RSA.

En este error, disparar el mismo mensaje encriptado una y otra vez en un servidor, pero modificando el relleno al final de los datos para invalidarlos y, por lo tanto, provocando algún tipo de comportamiento impredecible...

…no tomaría una cantidad constante de tiempo, suponiendo que estuviera cerca del objetivo en la red y pudiera adivinar de manera confiable cuánto tiempo tomaría la parte del proceso de transferencia de datos.

No todos los datos se procesan por igual

Si activa una solicitud, mide el tiempo que tarda la respuesta y resta el tiempo consumido en el envío y recepción de datos de red de bajo nivel, sabe cuánto tiempo tardó el servidor en realizar su cálculo interno para procesar la solicitud. .

Incluso si no está seguro de cuánto tiempo se utiliza en la red, puede buscar variaciones en los tiempos de ida y vuelta activando muchas solicitudes y recopilando muchas muestras.

Si la red es lo suficientemente confiable como para suponer que la sobrecarga de la red es en gran medida constante, es posible que pueda usar métodos estadísticos para inferir qué tipo de modificación de datos causa qué tipo de retraso adicional en el procesamiento.

A partir de esto, puede inferir algo sobre la estructura, o incluso el contenido, de los datos originales sin cifrar que se supone que deben mantenerse en secreto dentro de cada solicitud repetida.

Incluso si solo puede extraer un byte de texto sin formato, bueno, se supone que eso no debe suceder.

Así llamado ataques de tiempo de este tipo siempre son problemáticos, incluso si necesita enviar millones de paquetes falsos y cronometrarlos todos para tener alguna posibilidad de recuperar solo un byte de datos de texto sin formato...

…porque las redes son más rápidas, más predecibles y capaces de manejar mucha más carga que hace unos años.

Podría pensar que millones de paquetes traicioneros que le enviaron spam en, digamos, la siguiente hora se destacarían como un pulgar.

Pero “un millón de paquetes por hora más o menos de lo normal” simplemente ya no es una variación particularmente grande.

Error similar de "oráculo" en GnuTLS

Bueno, la misma persona que reportó el error de temporización del error corregido al fin en OpenSSL también reportó un error similar en GnuTLS aproximadamente al mismo tiempo.

Este tiene el identificador de error. CVE-2023-0361.

Aunque GnuTLS no es tan popular ni se usa tanto como OpenSSL, es probable que tenga varios programas en su propiedad de TI, o incluso en su propia computadora, que lo usen o lo incluyan, posiblemente incluidos FFmpeg, GnuPG, Mplayer, QEMU. , Rdesktop, Samba, Wget y Wireshark.

Irónicamente, la falla de tiempo en GnuTLS apareció en el código que se suponía que registraría errores de ataque de tiempo en primer lugar.

Como puede ver en la diferencia de código (diff) a continuación, el programador era consciente de que cualquier condicional (if ... then) utilizada para verificar y tratar un error de descifrado puede producir variaciones de tiempo, porque las CPU generalmente toman una cantidad de tiempo diferente dependiendo de la dirección en la que vaya su código después de una instrucción de "bifurcación".

(Eso es especialmente cierto para una rama que a menudo va en una dirección y rara vez en la otra, porque las CPU tienden a recordar, o almacenar en caché, el código que se ejecuta repetidamente para mejorar el rendimiento, lo que hace que el código que se toma con poca frecuencia se ejecute de manera detectable más lento).

Diferencia de código de gnutls-3.7.8/lib/auth/rsa.c contra 3.7.9

Pero el programador todavía quería registrar que podría estar ocurriendo un ataque, lo cual sucede si el if (ok) la prueba anterior falla y se ramifica en la else { ... } .

En este punto, el código llama al _gnutls_debug_log() función, que podría tardar bastante en hacer su trabajo.

Por lo tanto, el codificador insertó una llamada deliberada a _gnutls_no_log() existentes then { ... } parte del código, que pretende registrar un "ataque" cuando no lo hay, para tratar de igualar el tiempo que el código pasa en cualquier dirección que el if (ok) La instrucción de rama puede tomar.

Aparentemente, sin embargo, las dos rutas de código no eran lo suficientemente similares en el tiempo que usaron (o tal vez el _gnutls_debug_log() la función por sí sola no era lo suficientemente consistente para lidiar con diferentes tipos de error), y un atacante podría comenzar a distinguir los indicadores de descifrado después de un millón de intentos.

¿Qué hacer?

Si eres programador: la corrección del error aquí fue simple y siguió el principio de "menos es más".

El código en rosa anterior, que se consideró que no brindaba datos de detección de ataques terriblemente útiles de todos modos, simplemente se eliminó, con el argumento de que el código que no está allí no se puede compilar por error, independientemente de la configuración de compilación...

…y el código que no está compilado nunca puede ejecutarse, ya sea por accidente o por diseño.

Si es usuario de GnuTLS: la versión recientemente lanzada 3.7.9 y el “nuevo sabor del producto” 3.8.0 tenga esta solución, junto con varias otras, incluidas.

Si está ejecutando una distribución de Linux, busque actualizaciones para cualquier versión de biblioteca compartida administrada centralmente de GnuTLS que tenga, así como para aplicaciones que traigan su propia versión.

En Linux, busque archivos con el nombre libgnutls*.so para encontrar bibliotecas compartidas por ahí y buscar gnutls-cli para encontrar cualquier copia de la utilidad de línea de comandos que a menudo se incluye con la biblioteca.

Tu puedes correr gnutls-cli -vv para saber qué versión de libgnutls está vinculado dinámicamente a:

 $ gnutls-cli -vv gnutls-cli 3.7.9 <-- mi distribución de Linux recibió la actualización el viernes pasado (2023-02-10)

Sello de tiempo:

Mas de Seguridad desnuda