¿Es el error del corazón una manifestación del exploit de desbordamiento de búfer clásico en C?

En una de nuestras primeras conferencias de CS sobre seguridad, nos encontramos con el problema de C al no comprobar las presuntas longitudes de búfer y algunos ejemplos de las diferentes formas en que se podría aprovechar esta vulnerabilidad.

En este caso, parece que se trató de una operación de lectura maliciosa, donde la aplicación acaba de leer, sin embargo, muchos bytes de memoria.

  1. ¿Estoy en lo correcto al afirmar que el error Heartbleed es una manifestación del problema de la comprobación de la longitud del búfer C?

  2. ¿Por qué el uso malintencionado no causó un fallo de segmentación cuando intentó leer la memoria de otra aplicación?

  3. ¿El simple hecho de poner a cero la memoria antes de escribir en ella (y luego leerla) causó una falla de segmentación? ¿O esto varía entre los sistemas operativos? ¿O entre algún otro factor ambiental?

  4. Al parecer, las explotaciones del error no pueden ser identificadas. ¿Se debe a que la función de latido no se registra cuando se llama? De lo contrario, ¿es probable que cualquier solicitud de una cadena de ~ 64k sea maliciosa?

¿Estoy en lo correcto al afirmar que el error Heartbleed es una manifestación del problema de la comprobación de la longitud del búfer C?

Sí.

¿Es el error del corazón una manifestación del exploit de desbordamiento de búfer clásico en C?

No. El desbordamiento de búfer “clásico” es uno donde se escriben más datos en un búfer asignado a la stack de lo que puede contener, donde el agente hostil proporciona los datos escritos. Los datos hostiles desbordan el búfer y sobrescriben la dirección de retorno del método actual. Cuando el método finaliza, vuelve a una dirección que contiene el código de la elección del atacante y comienza a ejecutarlo.

Por el contrario, el defecto del corazón no sobrescribe un búfer y no ejecuta código arbitrario, solo lee fuera de límites en el código que es muy probable que tenga datos confidenciales cerca en la memoria.

¿Por qué el uso malintencionado no causó un fallo de segmentación cuando intentó leer la memoria de otra aplicación?

No intentó leer la memoria de otra aplicación. El exploit lee la memoria del proceso actual, no otro proceso.

¿Por qué el uso malintencionado no causó un error de segmentación cuando intentó leer la memoria fuera del límite del búfer?

Este es un duplicado de esta pregunta:

¿Por qué esto no da una falla de violación de segmentación?

Una falla de segmentación significa que tocó una página que el administrador de memoria del sistema operativo no le ha asignado. El error aquí es que tocó datos en una página válida que el administrador de almacenamiento no le ha asignado . Mientras la página sea válida, no obtendrá un error de seguridad. Por lo general, el administrador del montón solicita al sistema operativo una gran cantidad de memoria, y luego la divide entre diferentes asignaciones. Todas esas asignaciones se encuentran en páginas válidas de memoria en lo que respecta al sistema operativo.

La anulación de referencia es un error de seguridad simplemente porque el sistema operativo nunca hace que la página que contiene el puntero a cero sea una página válida.

Más generalmente: el comstackdor y el tiempo de ejecución no son necesarios para garantizar que un comportamiento indefinido dé como resultado un segfault; UB puede dar como resultado cualquier comportamiento, y eso incluye no hacer nada. Para más pensamientos sobre este asunto ver:

¿Se puede acceder a la memoria de una variable local fuera de su scope?

Tanto para mí como para quejarme de que UB siempre debería ser el equivalente de un error de seguridad en el código crítico para la seguridad, así como algunos consejos para una discusión sobre el análisis estático de la vulnerabilidad, consulte el artículo del blog de hoy:

http://ericlippert.com/2014/04/15/heartbleed-and-static-analysis/

¿El simple hecho de poner a cero la memoria antes de escribir en ella (y luego leerla) causó una falla de segmentación?

Improbable. Si la lectura fuera de límites no causa un error de seguridad, es poco probable que la escritura fuera de límites. Es posible que una página de memoria sea de solo lectura, pero en este caso parece poco probable.

Por supuesto, las consecuencias posteriores de poner a cero todo tipo de memoria que no se debe fallas de seguridad en todo el progtwig. Si hay un puntero en esa memoria de cero que más tarde anula, es una anulación de referencia que producirá un fallo de seguridad.

¿Esto varía entre los sistemas operativos?

La pregunta es vaga. Déjame reformularlo.

¿Los diferentes sistemas operativos y las diferentes bibliotecas en tiempo de ejecución de C / C ++ proporcionan diferentes estrategias para asignar memoria virtual, asignar memoria de almacenamiento dynamic e identificar cuándo el acceso a la memoria se sale de los límites?

Sí; Diferentes cosas son diferentes .

¿O entre algún otro factor ambiental?

¿Como?

Al parecer, las explotaciones del error no pueden ser identificadas. ¿Se debe a que la función de latido no se registra cuando se llama?

Correcto.

¿Es probable que cualquier solicitud de una cadena de ~ 64k sea maliciosa?

No estoy siguiendo tu línea de pensamiento. Lo que hace que la solicitud sea probablemente maliciosa es una falta de coincidencia entre los bytes enviados y los bytes solicitados para ser repetidos, no el tamaño de los datos solicitados para ser repetidos.

No se produce una falla de segmentación porque los datos a los que se accede son inmediatamente adyacentes a los datos solicitados, y generalmente están dentro de la memoria del mismo proceso. Podría causar una excepción si la solicitud fuera lo suficientemente grande, supongo, pero hacerlo no es del interés del explotador, ya que fallar el proceso evitaría que obtuvieran los datos.

Para una explicación clara, este comic de XKCD es difícil de mejorar:

introduzca la descripción de la imagen aquí