Comprender un desbordamiento de búfer basado en una pila real

1

mientras lees cómo y qué es un desbordamiento de búfer en la página owasp Vi documentación sobre un desbordamiento de búfer en el LibPNG

Se dijo que el siguiente código es vulnerable:

if (!(png_ptr->mode & PNG_HAVE_PLTE)) {
    /* Should be an error, but we can cope with it */
    png_warning(png_ptr, "Missing PLTE before tRNS");
}
else if (length > (png_uint_32)png_ptr->num_palette) {
    png_warning(png_ptr, "Incorrect tRNS chunk length");
    png_crc_finish(png_ptr, length);
    return;
}
...
png_crc_read(png_ptr, readbuf, (png_size_t)length);

Tengo problemas para entender por qué es vulnerable.

    
pregunta Fumerian Gaming 20.02.2017 - 18:45
fuente

2 respuestas

2

Desde el artículo wiki que has vinculado:

  

El código parece realizar la comprobación de límites de forma segura porque verifica el tamaño de la longitud variable, que luego utiliza para controlar la cantidad de datos copiados por png_crc_read (). Sin embargo, inmediatamente antes de que pruebe la longitud, el código realiza una comprobación en el modo png_ptr- > y, si falla esta comprobación, se emite una advertencia y el procesamiento continúa. Debido a que la longitud se prueba en un bloque else if, la longitud no se probaría si la primera verificación falla, y se usa a ciegas en la llamada a png_crc_read (), permitiendo potencialmente un desbordamiento del búfer de pila.

El código aparece para verificar si la longitud es más corta que el búfer. Pero la verificación de la longitud se realiza en un bloque else if . Cuando png_ptr->mode & PNG_HAVE_PLTE es falso, se registra una advertencia y la ejecución del programa continúa sin realizar la rama else y, por lo tanto, sin verificar length > (png_uint_32)png_ptr->num_palette . Eso significa que en cualquier situación en la que se genere la advertencia "Falta PLTE antes de tRNS", la longitud se pasa a png_crc_read sin que se haya verificado nunca.

Una explicación plausible de cómo se podría haber introducido este error es que "Falta PLTE antes de tRNS" solía ser una condición de error que abortó toda la función. En ese caso no había razón para molestar lo que sucedería después. Pero algún tiempo después, alguien lo redujo a una condición de advertencia sin verificar qué significaba eso para ningún código posterior.

Editar: Otra posibilidad de un desbordamiento de búfer en el código anterior podría ser si el valor de png_ptr->num_palette proviene de una fuente no confiable. Pero el ejemplo no menciona de dónde viene, así que dudo que eso sea lo que este ejemplo quiera ilustrar.

    
respondido por el Philipp 20.02.2017 - 19:33
fuente
1

Responderé con comentarios dentro del ejemplo.

Si, por alguna razón, el primer if se evalúa como TRUE , entonces todo lo que sucede es que se registra una advertencia.

if (!(png_ptr->mode & PNG_HAVE_PLTE)) {
    png_warning(png_ptr, "Missing PLTE before tRNS");
}

Sin embargo, si evalúa TRUE , la siguiente verificación de longitud nunca se ejecutará porque el bloque else-if se ha resuelto.

else if (length > (png_uint_32)png_ptr->num_palette) {
    png_warning(png_ptr, "Incorrect tRNS chunk length");
    png_crc_finish(png_ptr, length);
    return;
}

Ahora, cuando se llama a png_crc_read , es posible que nunca se haya hecho una verificación de longitud.

...
png_crc_read(png_ptr, readbuf, (png_size_t)length);

Esto es una vulnerabilidad si el atacante puede controlar el modo para forzar a la ruta del código a omitir la verificación de longitud. El atacante puede proporcionar una longitud mayor de la que debería ser posible, causando un desbordamiento del búfer. Dependiendo de dónde ocurra este desbordamiento, puede o no ser explotable.

    
respondido por el RoraΖ 20.02.2017 - 19:42
fuente

Lea otras preguntas en las etiquetas