Articulo de referencia

Desbordamiento del búfer de pila

En software, un desbordamiento de búfer de pila o sobrecarga de búfer de pila ocurre cuando un programa escribe en una dirección de memoria en la pila de llamadas del programa f...

En software, un desbordamiento de búfer de pila o sobrecarga de búfer de pila ocurre cuando un programa escribe en una dirección de memoria en la pila de llamadas del programa fuera de la estructura de datos prevista, que suele ser un búfer de longitud fija . [ 1 ] [ 2 ] Los errores de desbordamiento de búfer de pila se producen cuando un programa escribe más datos en un búfer ubicado en la pila de los que realmente se han asignado para ese búfer. Esto casi siempre resulta en la corrupción de datos adyacentes en la pila, y en los casos en que el desbordamiento se activó por error, a menudo provocará que el programa falle o funcione incorrectamente. El desbordamiento de búfer de pila es un tipo de mal funcionamiento de programación más general conocido como desbordamiento de búfer (o sobrecarga de búfer). [ 1 ] Es más probable que sobrellenar un búfer en la pila descarrile la ejecución del programa que sobrellenar un búfer en el montón porque la pila contiene las direcciones de retorno para todas las llamadas a funciones activas.

Un desbordamiento de búfer de pila puede ser provocado deliberadamente como parte de un ataque conocido comoAtaque de pila . Si el programa afectado se ejecuta con privilegios especiales o acepta datos de hosts de red no confiables (por ejemplo, unservidor web), entonces el error representa unavulnerabilidad de seguridad. Si el búfer de pila se llena con datos proporcionados por un usuario no confiable, dicho usuario puede corromper la pila de tal manera que inyecte código ejecutable en el programa en ejecución y tome el control del proceso. Este es uno de los métodos más antiguos y confiables que utilizanlos atacantespara obtener acceso no autorizado a una computadora. [ 3 ] [ 4 ] [ 5 ]

Explotación de desbordamientos de búfer de pila

El método canónico para explotar un desbordamiento de búfer basado en la pila consiste en sobrescribir la dirección de retorno de la función con un puntero a datos controlados por el atacante (generalmente en la propia pila). [ 3 ] [ 6 ] Esto se ilustra en strcpy()el siguiente ejemplo:

#include <string.h>void foo ( char * bar ) { char c [ 12 ];strcpy ( c , bar ); // sin comprobación de límites }int main ( int argc , char * argv []) { foo ( argv [ 1 ]); return 0 ; }

Este código toma un argumento de la línea de comandos y lo copia a una variable de pila local c. Esto funciona correctamente para argumentos de línea de comandos menores de 12 caracteres (como se puede ver en la figura B a continuación). Cualquier argumento mayor de 11 caracteres provocará la corrupción de la pila. (El número máximo de caracteres que se puede almacenar de forma segura es uno menos que el tamaño del búfer, ya que en el lenguaje de programación C, las cadenas terminan con un byte nulo. Por lo tanto, una entrada de doce caracteres requiere trece bytes para su almacenamiento: la entrada seguida del byte cero centinela. El byte cero termina sobrescribiendo una ubicación de memoria que se encuentra un byte más allá del final del búfer).

El programa se carga foo()con varias entradas:

En la figura C anterior, cuando se proporciona un argumento mayor de 11 bytes en la línea de comandos, foo()se sobrescriben los datos de la pila local, el puntero de marco guardado y, lo que es más importante, la dirección de retorno. Cuando foo()regresa, se extrae la dirección de retorno de la pila y se salta a esa dirección (es decir, se empiezan a ejecutar instrucciones desde esa dirección). Por lo tanto, el atacante ha sobrescrito la dirección de retorno con un puntero al búfer de la pila char c[12], que ahora contiene datos proporcionados por el atacante. En una explotación real de desbordamiento de búfer de pila, la cadena de "A" sería en su lugar un shellcode adecuado para la plataforma y la función deseada. Si este programa tuviera privilegios especiales (por ejemplo, el bit SUID configurado para ejecutarse como superusuario ), el atacante podría usar esta vulnerabilidad para obtener privilegios de superusuario en la máquina afectada. [ 3 ]

El atacante también puede modificar los valores de las variables internas para explotar ciertos errores. Con este ejemplo:

#include <stdio.h> #include <string.h>void foo ( char * bar ) { float myFloat = 10.5 ; // Addr = 0x0023FF4C char c [ 28 ]; // Addr = 0x0023FF30// Imprimirá 10.500000 printf ( "myFloat value = %f \n " , myFloat );/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Mapa de memoria:  @ : c memoria asignada  # : myFloat memoria asignada *c *myFloat  0x0023FF30 0x0023FF4C  | |  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####  foo("¡¡¡¡¡mi cadena es demasiado larga!!!!! XXXXX"); memcpy pondrá 0x1010C042 (little endian) en el valor myFloat.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/memcpy ( c , bar , strlen ( bar )); // sin comprobación de límites...// Imprimirá 96.031372 printf ( "myFloat value = %f \n " , myFloat ); }int main ( int argc , char * argv []) { foo ( "mi cadena es demasiado larga !!!!! \x10\x10\xc0\x42 " ); return 0 ; }

Generalmente se utilizan dos métodos para alterar la dirección almacenada en la pila: directo e indirecto. Los atacantes comenzaron a desarrollar ataques indirectos, que tienen menos dependencias, para eludir las medidas de protección implementadas para reducir los ataques directos. [ 7 ]

Varias plataformas presentan sutiles diferencias en la implementación de la pila de llamadas que pueden afectar el funcionamiento de un exploit de desbordamiento de búfer de pila. Algunas arquitecturas de máquina almacenan la dirección de retorno de nivel superior de la pila de llamadas en un registro. Esto significa que cualquier dirección de retorno sobrescrita no se utilizará hasta un desenrollado posterior de la pila de llamadas. Otro ejemplo de un detalle específico de la máquina que puede afectar la elección de técnicas de explotación es el hecho de que la mayoría de las arquitecturas de máquina de estilo RISC no permiten el acceso no alineado a la memoria. [ 8 ] Combinado con una longitud fija para los códigos de operación de la máquina, esta limitación puede hacer que la técnica de salto a la pila sea casi imposible de implementar (con la única excepción de cuando el programa contiene el improbable código para saltar explícitamente al registro de la pila). [ 9 ] [ 10 ]

Pilas que crecen

Dentro del tema de desbordamientos de búfer de pila, una arquitectura frecuentemente discutida pero raramente vista es aquella en la que la pila crece en la dirección opuesta. Este cambio de arquitectura se sugiere con frecuencia como solución al problema de desbordamiento de búfer de pila porque cualquier desbordamiento de un búfer de pila que ocurra dentro del mismo marco de pila no puede sobrescribir el puntero de retorno. Sin embargo, cualquier desbordamiento que ocurra en un búfer de un marco de pila anterior sobrescribirá un puntero de retorno y permitirá la explotación maliciosa del error. [ 11 ] Por ejemplo, en el ejemplo anterior, el puntero de retorno para foono se sobrescribirá porque el desbordamiento ocurre realmente dentro del marco de pila para memcpy. Sin embargo, debido a que el búfer que se desborda durante la llamada a memcpyreside en un marco de pila anterior, el puntero de retorno para memcpytendrá una dirección de memoriafoo numéricamente mayor que el búfer. Esto significa que en lugar de que se sobrescriba el puntero de retorno para , memcpyse sobrescribirá el puntero de retorno para . Como mucho, esto significa que aumentar el tamaño de la pila en la dirección opuesta modificará algunos detalles de cómo se pueden explotar los desbordamientos de búfer de la pila, pero no reducirá significativamente el número de errores explotables.

Planes de protección

A lo largo de los años, se han desarrollado varios esquemas de integridad del flujo de control para inhibir la explotación maliciosa del desbordamiento del búfer de pila. Estos generalmente se pueden clasificar en tres categorías:

  • Detectar que se ha producido un desbordamiento del búfer de la pila y, por lo tanto, evitar la redirección del puntero de instrucción a código malicioso.
  • Evita la ejecución de código malicioso desde la pila sin detectar directamente el desbordamiento del búfer de la pila.
  • Aleatorizar el espacio de memoria de tal manera que encontrar código ejecutable se vuelva poco fiable.

Canarios apilados

Los canarios de pila, llamados así por su analogía con un canario en una mina de carbón , se utilizan para detectar un desbordamiento de búfer de pila antes de que se ejecute código malicioso. Este método consiste en colocar un pequeño número entero, cuyo valor se elige aleatoriamente al inicio del programa, en la memoria justo antes del puntero de retorno de la pila. La mayoría de los desbordamientos de búfer sobrescriben la memoria desde direcciones de memoria inferiores a superiores, por lo que para sobrescribir el puntero de retorno (y así tomar el control del proceso) también debe sobrescribirse el valor del canario. Este valor se verifica para asegurar que no haya cambiado antes de que una rutina utilice el puntero de retorno en la pila. [ 2 ] Esta técnica puede aumentar considerablemente la dificultad de explotar un desbordamiento de búfer de pila, ya que obliga al atacante a obtener el control del puntero de instrucción por medios no tradicionales, como corromper otras variables importantes en la pila. [ 2 ]

Pila no ejecutable

Otro método para prevenir la explotación de desbordamiento de búfer de pila consiste en aplicar una política de memoria en la región de memoria de la pila que impida la ejecución desde la pila ( W^X , "Write XOR Execute"). Esto significa que, para ejecutar shellcode desde la pila, un atacante debe encontrar una manera de deshabilitar la protección de ejecución desde la memoria o encontrar una manera de colocar su carga útil de shellcode en una región de memoria no protegida. Este método se está popularizando ahora que la mayoría de los procesadores de escritorio ofrecen soporte de hardware para la bandera de no ejecución.

Si bien este método previene la explotación canónica de desbordamiento de pila, los desbordamientos de pila pueden explotarse de otras maneras. En primer lugar, es común encontrar formas de almacenar código malicioso en regiones de memoria no protegidas como el montón, por lo que se necesita muy poco cambio en la forma de explotación. [ 12 ]

Otro ataque es el llamado método de retorno a libc para la creación de shellcode. En este ataque, la carga útil maliciosa cargará la pila no con shellcode, sino con una pila de llamadas adecuada, de modo que la ejecución se dirija a una cadena de llamadas a la biblioteca estándar, generalmente con el efecto de deshabilitar las protecciones de ejecución de memoria y permitir que el shellcode se ejecute con normalidad. [ 13 ] Esto funciona porque la ejecución nunca se dirige realmente a la pila misma.

Una variante de return-to-libc es la programación orientada a retorno (ROP), que establece una serie de direcciones de retorno, cada una de las cuales ejecuta una pequeña secuencia de instrucciones de máquina seleccionadas dentro del código del programa o las bibliotecas del sistema existentes, secuencia que finaliza con un retorno. Estos llamados gadgets realizan alguna manipulación simple de registros o una ejecución similar antes de regresar, y al combinarlos se logran los objetivos del atacante. Incluso es posible utilizar programación orientada a retorno "sin retorno" explotando instrucciones o grupos de instrucciones que se comportan de manera muy similar a una instrucción de retorno. [ 14 ]

Aleatorización

En lugar de separar el código de los datos, otra técnica de mitigación consiste en introducir aleatorización en el espacio de memoria del programa en ejecución. Dado que el atacante necesita determinar dónde reside el código ejecutable que puede utilizar, se proporciona una carga útil ejecutable (con una pila ejecutable) o se construye una utilizando la reutilización de código, como en ret2libc o la programación orientada a retornos (ROP). En teoría, la aleatorización de la distribución de la memoria impedirá que el atacante sepa dónde se encuentra el código. Sin embargo, las implementaciones normalmente no aleatorizan todo; por lo general, el ejecutable se carga en una dirección fija y, por lo tanto, incluso cuando se combina ASLR (aleatorización de la distribución del espacio de direcciones) con una pila no ejecutable, el atacante puede utilizar esta región fija de memoria. Por consiguiente, todos los programas deben compilarse con PIE (ejecutables independientes de la posición) de manera que incluso esta región de memoria se aleatorice. La entropía de la aleatorización es diferente de una implementación a otra, y una entropía suficientemente baja puede ser en sí misma un problema en términos de fuerza bruta en el espacio de memoria que se aleatoriza.

Contramedidas para eludir

Las medidas de mitigación anteriores dificultan los pasos de la explotación. Sin embargo, aún es posible explotar un desbordamiento de búfer de pila si existen ciertas vulnerabilidades o si se cumplen ciertas condiciones. [ 15 ]

Bypass canario de pila

Fuga de información con explotación de vulnerabilidad de formato de cadena

Un atacante puede explotar la vulnerabilidad de formato de cadena para revelar las ubicaciones de memoria en el programa vulnerable. [ 16 ]

Omisión de pila no ejecutable

Cuando se habilita la Prevención de Ejecución de Datos para prohibir cualquier acceso de ejecución a la pila, el atacante aún puede usar la dirección de retorno sobrescrita (el puntero de instrucción) para apuntar a datos en un segmento de código ( .text en Linux) o en cualquier otra sección ejecutable del programa. El objetivo es reutilizar código existente. [ 17 ]

Cadena de cuerda

Consiste en sobrescribir el puntero de retorno un poco antes de una instrucción de retorno (ret en x86) del programa. Las instrucciones entre el nuevo puntero de retorno y la instrucción de retorno se ejecutarán y la instrucción de retorno volverá a la carga útil controlada por el explotador. [ 17 ]

Cadena Jop

La programación orientada a saltos es una técnica que utiliza instrucciones de salto para reutilizar código en lugar de la instrucción ret. [ 18 ]

Derivación aleatoria

Una limitación de la implementación de ASLR en sistemas de 64 bits es su vulnerabilidad a ataques de divulgación de memoria y fuga de información. El atacante puede iniciar el ROP revelando una única dirección de función mediante un ataque de fuga de información. La siguiente sección describe una estrategia similar existente para vulnerar la protección ASLR. [ 19 ]

Ejemplos notables

  • El gusano Morris, en 1988, se propagó en parte explotando un desbordamiento de búfer de pila en el servidor finger de Unix . [ 20 ]
  • El gusano Slammer se propagó en 2003 explotando un desbordamiento de búfer de pila en el servidor SQL de Microsoft . [ 21 ]
  • El gusano Blaster se propagó en 2003 aprovechando un desbordamiento de búfer de pila en el servicio DCOM de Microsoft .
  • El gusano Witty se propagó en 2004 explotando un desbordamiento de búfer de pila en el agente de escritorio BlackICE de Internet Security Systems . [ 22 ]
  • Hay un par de ejemplos de la Wii que permiten ejecutar código arbitrario en un sistema sin modificar. El "Twilight hack", que consiste en darle un nombre largo al caballo del personaje principal en The Legend of Zelda: Twilight Princess , [ 23 ] y "Smash Stack" para Super Smash Bros. Brawl, que consiste en usar una tarjeta SD para cargar un archivo especialmente preparado en el editor de niveles del juego. Aunque ambos pueden usarse para ejecutar cualquier código arbitrario, el último se usa a menudo simplemente para recargar Brawl con las modificaciones aplicadas. [ 24 ]

Véase también

Referencias

  1. 1 2 Fithen, William L.; Seacord, Robert (27-03-2007). "VT-MB. Violación de los límites de la memoria" . US CERT .
  2. 1 2 3 Dowd, Mark; McDonald, John; Schuh, Justin (noviembre de 2006). El arte de la evaluación de la seguridad del software . Addison Wesley . págs. 169–196 . ISBN  0-321-44442-6.
  3. 1 2 3 Levy, Elias (1996-11-08). "Destrozando la pila por diversión y beneficio" . Phrack . 7 (49): 14.
  4. Pincus, J.; Baker, B. (julio-agosto de 2004). "Más allá del desbordamiento de pila: avances recientes en la explotación de desbordamientos de búfer" (PDF) . IEEE Security & Privacy . 2 (4): 20– 27. Bibcode : 2004ISPri...2d..20P . doi : 10.1109/MSP.2004.36 . S2CID 6647392 . 
  5. Burebista. "Stack Overflows" (PDF) . Archivado del original (PDF) el 28 de septiembre de 2007.
  6. Bertrand, Louis (2002). "OpenBSD: Corrige los errores, asegura el sistema" . MUSESS '02: Simposio de Ingeniería de Software de la Universidad McMaster . Archivado del original el 30 de septiembre de 2007.
  7. Kuperman, Benjamin A.; Brodley, Carla E.; Ozdoganoglu, Hilmi; Vijaykumar, TN; Jalote, Ankit (noviembre de 2005). "Detección y prevención de ataques de desbordamiento de búfer de pila" . Communications of the ACM . 48 (11): 50– 56. doi : 10.1145/1096000.1096004 . ISSN 0001-0782 . S2CID 120462 .  
  8. pr1. "Explotando vulnerabilidades de desbordamiento de búfer SPARC" .{{cite web}}: CS1 maint: nombres numéricos: lista de autores ( enlace )
  9. Curious (2005-01-08). "Ingeniería inversa: cracking de PowerPC en Mac OS X con GDB" . Phrack . 11 (63): 16.
  10. Sovarel, Ana Nora; Evans, David; Paul, Nathanael. ¿ Dónde está el FEEB? La efectividad de la aleatorización del conjunto de instrucciones (Informe).
  11. Zhodiac (2001-12-28). "HP-UX (PA-RISC 1.1) Desbordamientos" . Phrack . 11 (58): 11.
  12. Foster, James C.; Osipov, Vitaly; Bhalla, Nish; Heinen, Niels (2005). Ataques de desbordamiento de búfer: detección, explotación y prevención (PDF) . Estados Unidos de América: Syngress Publishing, Inc. ISBN 1-932266-67-4.
  13. Nergal (2001-12-28). "Los exploits avanzados de retorno a lib(c): estudio de caso de PaX" . Phrack . 11 (58): 4.
  14. Checkoway, S.; Davi, L.; Dmitrienko, A.; Sadeghi, AR; Shacham, H.; Winandy, M. (octubre de 2010). «Programación orientada a retornos sin retornos». Actas de la 17.ª conferencia ACM sobre seguridad informática y de comunicaciones - CCS '10 . págs. 559–572 . doi : 10.1145/1866307.1866370 . ISBN  978-1-4503-0245-6. S2CID 207182734 . 
  15. Shoshitaishvili, Yan. "Errores de memoria, seguridad de programas" . pwn college . Consultado el 7 de septiembre de 2024 .
  16. Butt, Muhammad Arif; Ajmal, Zarafshan; Khan, Zafar Iqbal; Idrees, Muhammad; Javed, Yasir (enero de 2022). "Un estudio exhaustivo de las técnicas de mitigación de desbordamiento de búfer que evitan el paso del búfer" . Applied Sciences . 12 (26): 6702. doi : 10.3390/app12136702 . ISSN 2076-3417 . 
  17. 1 2 Butt, Muhammad Arif; Ajmal, Zarafshan; Khan, Zafar Iqbal; Idrees, Muhammad; Javed, Yasir (enero de 2022). "Un estudio exhaustivo de las técnicas de mitigación de desbordamiento de búfer que evitan el paso del búfer" . Applied Sciences . 12 (13): 12– 13. doi : 10.3390/app12136702 . ISSN 2076-3417 . 
  18. ^ Sécurité matérielle des systèmes (en francés). 2022-09-03.
  19. Butt, Muhammad Arif; Ajmal, Zarafshan; Khan, Zafar Iqbal; Idrees, Muhammad; Javed, Yasir (enero de 2022). "Un estudio exhaustivo de las técnicas de mitigación de desbordamiento de búfer que evitan el paso del búfer" . Applied Sciences . 12 (16): 6702. doi : 10.3390/app12136702 . ISSN 2076-3417 . 
  20. "Informe sobre el gusano informático" . 7 de noviembre de 1988.
  21. "Twilight Hack - WiiBrew" . wiibrew.org . Consultado el 18 de enero de 2018 .
  22. "Smash Stack - WiiBrew" . wiibrew.org . Consultado el 18 de enero de 2018 .
Obtenido de " https://en.wikipedia.org/w/index.php?title=Stack_buffer_overflow&oldid=1353796029#stack_smashing "