Logotipo de Zephyrnet

OpenSSH corrige el error de memoria doble libre que se puede introducir en la red

Fecha:

La distribución del sistema operativo de código abierto OpenBSD es bien conocida entre los administradores de sistemas, especialmente aquellos que administran servidores, por su enfoque en la seguridad por encima de la velocidad, las funciones y los front-end sofisticados.

Oportunamente, tal vez, su logotipo es un pez globo, inflado, con sus púas listas para repeler a cualquier pirata informático astuto que pueda aparecer.

Pero el equipo de OpenBSD es probablemente mejor conocido no por toda su distribución, sino por el kit de herramientas de acceso remoto. OpenSSH que fue escrito a fines de la década de 1990 para incluirlo en el propio sistema operativo.

SSH, abreviatura de cubierta segura, fue creado originalmente por el informático finlandés Tatu Ylonen a mediados de la década de 1990 con la esperanza de destetar a los administradores de sistemas del hábito arriesgado de usar el protocolo Telnet.

El problema con Telnet

Telnet fue notablemente simple y efectivo: en lugar de conectar cables físicos (o usar un módem a través de una línea telefónica) para hacer una conexión de teletipo a servidores remotos, usó una conexión de RED de TELetipo en su lugar.

Básicamente, los datos que normalmente fluían de un lado a otro a través de una conexión en serie dedicada o una línea telefónica de acceso telefónico se enviaban y recibían a través de Internet, utilizando una conexión de red TCP con conmutación de paquetes en lugar de un enlace punto a punto con conmutación de circuitos. .

¡El mismo sistema familiar de inicio de sesión, conexiones más económicas, sin necesidad de líneas de datos dedicadas!

La gran falla de Telnet, por supuesto, era su falta total de encriptación, por lo que olfatear la sesión exacta de su terminal era trivial, lo que permitía a los piratas informáticos ver cada comando que ingresaba (incluso los errores que cometía y todas las veces que presionaba). [Backspace]), y cada byte de salida producido...

…y, por supuesto, tu nombre de usuario y contraseña al iniciar la sesión.

Cualquier persona en su ruta de red no solo podría reconstruir fácilmente sus sesiones de administrador de sistemas en tiempo real en su propia pantalla, sino que probablemente también podría alterar su sesión modificando los comandos que envió al servidor remoto y falsificando las respuestas para que no se diera cuenta. el subterfugio

Incluso podrían configurar un servidor impostor, atraerlo y hacer que sea sorprendentemente difícil para usted detectar el engaño.

Cifrado fuerte FTW

El SSH de Ylönen tenía como objetivo agregar una capa de encriptación y autenticación fuertes a cada extremo de una sesión similar a Telnet, creando una cubierta segura (eso es lo que significa el nombre, si alguna vez te lo has preguntado, aunque casi todo el mundo lo llama simplemente ess-ess-aitch estos días).

Fue un éxito instantáneo y los administradores de sistemas de todo el mundo adoptaron rápidamente el protocolo.

OpenSSH pronto siguió, como mencionamos anteriormente, apareciendo por primera vez a finales de 1999 como parte de la OpenBSD 2.6 en libertad.

El equipo de OpenBSD quería crear una implementación gratuita, confiable y de código abierto del protocolo que ellos y cualquier otra persona podría usar, sin ninguna de las complicaciones comerciales o de licencia que habían obstaculizado la implementación original de Ylönen en los años inmediatamente posteriores a su lanzamiento.

De hecho, si ejecuta el servidor SSH de Windows y se conecta a él desde una computadora con Linux en este momento, es casi seguro que confiará en la implementación de OpenSSH en ambos extremos.

El protocolo SSH también se usa en otros servicios cliente-servidor populares, incluidos SCP y SFTP, abreviatura de copia segura y FTP seguro respectivamente. SSH significa vagamente, "conectarse de forma segura y ejecutar un comando SHell en el otro extremo", generalmente para inicios de sesión interactivos, porque el programa Unix para un comando shell generalmente es /bin/sh. SCP es similar, pero para copiar archivos, porque el comando de copia de archivos de Unix generalmente se llama /bin/cp, y SFTP se nombra de la misma manera.

OpenSSH no es el único conjunto de herramientas de SSH en la ciudad.

Otras implementaciones conocidas incluyen: libssh2, para desarrolladores que desean incorporar compatibilidad con SSH directamente en sus propias aplicaciones; Dropbear, un servidor SSH reducido del codificador australiano matt johnston eso se encuentra ampliamente en los llamados dispositivos IoT (Internet de las cosas), como enrutadores domésticos e impresoras; y PuTTY, una popular colección gratuita de herramientas relacionadas con SSH para Windows de un desarrollador independiente de código abierto Simon Tatham en Inglaterra.

Pero si es un usuario habitual de SSH, es casi seguro que se haya conectado al menos a un servidor OpenSSH hoy, sobre todo porque la mayoría de las distribuciones de Linux actuales lo incluyen como su herramienta estándar de acceso remoto, y Microsoft ofrece tanto un cliente OpenSSH como un OpenSSH. servidor como componentes oficiales de Windows en estos días.

Corrección de errores doblemente libre

OpenSSH versión 9.2 acaba de salir y el notas de la versión informe de la siguiente manera:

Esta versión contiene correcciones para […] un problema de seguridad de la memoria. [Este error] no se cree que sea explotable, pero informamos la mayoría de las fallas de memoria accesibles en la red como errores de seguridad.

El bicho afecta sshd, el servidor OpenSSH (el -d sufijo significa demonio, el nombre de Unix para el tipo de proceso en segundo plano que Windows llama un de coches):

sshd(8): corrige una falla de memoria libre doble de autenticación previa introducida en OpenSSH 9.1. No se cree que esto sea explotable, y ocurre en el proceso de autorización previa sin privilegios que está sujeto a chroot (2) y está protegido en la mayoría de las plataformas principales.

Un error doble libre significa que un bloque de memoria que ya devolviste al sistema operativo para ser reutilizado en otras partes de tu programa...

…luego será devuelto nuevamente por una parte del programa que en realidad ya no “posee” esa memoria, pero no sabe que no es así.

(O devuelto deliberadamente a instancias del código que está tratando de provocar el error a propósito para convertir un vulnerabilidad en una explotar.)

Esto puede conducir a errores sutiles y difíciles de resolver, especialmente si el sistema marca el bloque liberado como disponible cuando se ejecuta por primera vez. free() sucede, luego lo asigna a otra parte de su código cuando solicita memoria a través de malloc(), y luego marca el bloque libre una vez más cuando la llamada superflua a free() aparece.

Eso lo deja en el tipo de situación que experimenta cuando se registra en un hotel que dice: “¡Oh, buenas noticias! Pensamos que estábamos llenos, pero otro huésped decidió irse temprano, para que pueda quedarse con su habitación”.

Incluso si la habitación está cuidadosamente limpia y preparada para los nuevos ocupantes cuando ingresa y, por lo tanto, parece que se asignó correctamente para su uso exclusivo, aún debe confiar en que la tarjeta de acceso del huésped anterior se canceló correctamente y que su " salida anticipada” no fue una artimaña astuta para volver a escondidas más tarde el mismo día y robar su computadora portátil.

Corrección de errores para corrección de errores

Irónicamente, si observa el historial reciente del código de OpenSSH, verá que OpenSSH tenía un error modesto en una función llamada compat_kex_proposal(), utilizado para verificar qué tipo de algoritmo de intercambio de claves usar al configurar una conexión.

Pero corregir ese modesto error introdujo una vulnerabilidad más grave en su lugar.

Por cierto, la presencia del error en una parte del software que se usa durante la configuración de una conexión es lo que hace que esto se denomine preautenticación accesible por red vulnerabilidad (o error de autorización previa para abreviar).

El error de doble liberación ocurre en el código que necesita ejecutarse después de un cliente ha iniciado una sesión remota, pero antes ha tenido lugar cualquier acuerdo de clave o autenticación, por lo que la vulnerabilidad puede, en teoría, desencadenarse antes de que se presenten contraseñas o claves criptográficas para su validación.

En OpenSSH 9.0, compat_kex_proposal se veía algo como esto (muy simplificado aquí):

char* compat_kex_proposal(char* suggestion) { if (condition1) { return suggestion; } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { suggestion = allocatenewstring2(); } if (isblank(suggestion)) { error(); } return suggestion; }

La idea es que la persona que llama pase su propio bloque de memoria que contiene una cadena de texto que sugiere una configuración de intercambio de claves y obtenga una aprobación para usar la misma sugerencia que envió, o una cadena de texto recién asignada con una sugerencia actualizada. .

El error es que si la condición 1 es falsa pero las condiciones 2 y 3 son verdaderas, el código asigna dos nuevas cadenas de texto, pero solo devuelve una.

El bloque de memoria asignado por allocatenewstring1() nunca se libera, y cuando la función regresa, su dirección de memoria se pierde para siempre, por lo que no hay forma de que ningún código free() en el futuro.

Ese bloque está esencialmente abandonado, causando lo que se conoce como un pérdida de memoria.

Con el tiempo, esto podría causar problemas, tal vez incluso obligando al servidor a apagarse para recuperarse de la sobrecarga de memoria.

En OpenSSH 9.1, el código se actualizó en un intento de evitar asignar dos cadenas pero abandonar una de ellas:

/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion){ char* previousone = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { previousone = suggestion; suggestion = allocatenewstring2(); } free(previousone); } if (isblank(suggestion()) { error(); } return suggestion; }

Esto tiene el error de doble libertad, porque si la condición 1 y la condición 2 son falsas, pero la condición 3 es verdadera, entonces el código asigna una nueva cadena para enviar como respuesta...

… pero libera incorrectamente la cadena que la persona que llamó pasó originalmente, porque la función allocatenewstring1() nunca recibe una llamada para actualizar la variable suggestion.

La cadena de sugerencia pasada es la memoria que pertenece a la persona que llama, y que, por lo tanto, la persona que llama se liberará más adelante, lo que conducirá al peligro de doble libertad.

En OpenSSH 9.2, el código se ha vuelto más cauteloso y realiza un seguimiento de los tres posibles bloques de memoria utilizados: el original suggestion (memoria propiedad de otra persona) y dos posibles cadenas nuevas que podrían asignarse en el camino:

/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion) { char* newone = NULL; char* newtwo = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { newone = allocatenewstring1(); } if (condition3) { newtwo = allocatenewstring2(); } free(newone); newone = newtwo; } if (isblank(newone)) { error(); } return newone; }

Si la condición 1 es verdadera, se usa una nueva copia de la cadena pasada, por lo que la persona que llama puede más tarde free() la memoria de su cadena pasada cuando lo deseen.

Si pasamos la condición 1, y la condición 2 es verdadera pero la condición 3 es falsa, entonces la sugerencia alternativa creada por allocatenewstring1() es devuelto, y el transferido suggestion la cuerda se deja sola.

Si la condición 2 es falsa y la condición 3 es verdadera, entonces se genera y devuelve una nueva cadena, y la suggestion la cuerda se deja sola.

Si tanto la condición 2 como la condición 3 son verdaderas, entonces se asignan dos nuevas cadenas en el camino; el primero se libera porque no se necesita; se devuelve el segundo; y el pasado suggestion la cuerda se deja sola.

solicite RTxM para confirmar que si llamas free(newone) cuando newone is NULL, entonces "no se realiza ninguna operación", porque siempre es seguro free(NULL). Sin embargo, muchos programadores aún se protegen firmemente contra esto con código como if (ptr != NULL) { free(ptr); }.

¿Qué hacer?

Como sugiere el equipo de OpenSSH, la explotación de este error será difícil, sobre todo debido a los privilegios limitados que el sshd programa tiene mientras está configurando la conexión para su uso.

Sin embargo, lo informaron como un agujero de seguridad porque eso es lo que es, así que asegúrese de haber actualizado a OpenSSH 9.2.

Y si está escribiendo código en C, recuerde que, independientemente de la experiencia que tenga, es fácil equivocarse en la gestión de la memoria...

…así que ten cuidado ahí fuera.

(Sí, Rust y sus amigos modernos lo harán ayudarle a escribir el código correcto, pero a veces aún necesitará usar C, e incluso Rust no puede garantizar que evitar que escribas código incorrecto si programa imprudentemente!)


punto_img

Información más reciente

punto_img