Introducción a Buffer overflow

Conceptos fundamentales para Buffer overflow.

Introducción

El desbordamiento de memoria de búfer se remontan a la década de 1970, sin embargo hasta finales de los 80 no se produjo el primer ataque de este tipo, el servicio “finger” de UNIX fue el explotado mediante el desbordamiento de pila.

Los desbordamientos de búfer se siguen produciendo en aplicaciones de software, y su explotación puede depender de muchos factores, ya sea de las opciones de los compiladores o la seguridad del sistema operativo.

¿Qué es un Buffer?

Un buffer es un espacio temporal de memoria fisica que se usa para almacenar información mientras está se envia de un lado a otro. Es una respuesta rápida que se utiliza para optimizar un proceso de transferencia de datos, estos suelen estar en la memoria RAM. Los búferes estan diseñados para poder contener una cantidad específica de datos, si el programa no tiene una instrucción incoporada, lo datos se sobrescribiran en los datos de la memoria adyacente al búfer.

¿Qué es un registro?

La definición más simple de un registro es entenderlo como si fuera variable. Es un región de memoria en la que podemos almacenar y leer datos. La diferencia con las variables que nosotros definimos es que lo registros sirven de un próposito concreto y son limitados. Un registro puede variar según la arquitectura de CPU pueden ser de 32 bits o 64 bits.

Registros de CPU

Según la arquitectura hay nomenclaturas diferentes para cada registro:

  • Registros de 64 bits: RAX, RBC, RCX, RDX, RSI, RDI, RBP, RSP

  • Registros de 16 bits: AX, BX, CX, DX, SI, DI, BP, SP, IP

  • Registros de 8bits: AH, AL, BH, BL, CH, CL, DH, DL

En este caso nos centraremos en los registros de 32 bits.

Nomenclatura
Nombre Completo
Uso

EIP

Extended Instruction Pointer

Es la siguiente dirección de memoria que se debería ejecutar.

EAX

Extended Accumulator Register

Almacena de forma temporal cualquier dirección de retorno.

ESI

Extended Source Index

Contiene la dirección de memoria de los datos de entrada.

EBX

Extended Base Register

Almacena datos y direcciones de memoria.

ESP

Extended Stack Pointer

Se usa para referenciar el inicio de un hilo.

EBP

Extended Base Pointer

Indica la dirección de memoria del final de un hilo.

Little Indian y Big Indian

Son dos estilos diferentes de almacenar los datos en memoria.

En little Indian, el byte significativo más pequeño se almacena en la dirección más baja o la primera, mientras que el byte significativo más grande se almacena en la dirección más alta. Basícamente el byte más pequeño se almacena el primero y el byte más alto se almacena el último.

En Big Indian,el byte más significativo se almacena en la dirección más baja (o primera), y el byte menos significativo se almancena en la dirección más alta.

¿Qué es un Buffer Overflow?

Un Buffer overflow también conocido como desborde de memoria, se produce cuando un programa excede el uso de cantidad de memoria asignada, lo cual provoca que los datos de entrada ocupen zonas de memoria adyacentes, donde se podria ejecutar código.

La explotación de esta vulnerabilidad se centra en sobrescribir la dirección de retorno (EIP). De esta forma se puede redirigir el flujo de ejecucción del programa haciendo que pueda ir a un código desarrollado por el atacante, también se podría producir un ataque de denegación de servicio.

Tipos de Buffer Overflow

  • Stack overflow: El desbordamiento de pila es un tipo de error que se produce cuando un programa informático intenta usar más espacio de memoria en la pila del que está asignado.La pila de llamadas , denominada “segmento de pila” es un búfer de tamaño fijo que almacena variables y funciones locales y datos de dedirección de retorno durante la ejecucción. La pila de llamadas se adhiere a un tipo de arquitectura de último en entrar, primero en salir (LIFO). Cada función tiene su marco de pila, esto se añade a la parte superior de la pila de llamadas.Este marco de pila permanece en la memoria hasta que la función termine de ejecutarse, liberando así memoria para otros marcos de pila. El tamaño de una pila se suele definir a la hora del inicio del programa, su tamaño depende de determinados facotres , como la arquitectura del ordenador , el lenguaje de programación, cantidad de memoria utilizada. Si un programa demanda más memoria de la que hay disponible se produce un desbordamiento de pila, lo que puede provocar que el programa se bloqueé.

  • Heap overflow: A diferencia de la pila de llamadas, existe lo que se denomina como segmento, es un espacio de memoria que se asigna dinámicamente y que se almacena en variables globales. Este segmento también es igual de vulnerable que el de la “pila de llamadas(Stack)".Con los heaps, los que desarrollan los programas son responsables de reasignar la memoria, si no lo hacen de la forma correcta puede producirse un desbordamiento de pila. Este desbordamiento también puede ocurrir cuando las variables almacenadas contienen más datos que la cantidad de memoria asignada.

Diferencias entre Stack y Heap

#include <stdio.h>
#include <stdlib.h>
void foo(int valor) {
  unsigned char c;
  unsigned char *ptr = malloc(1);
  printf("Stack: %p | Heap: %p\n", &c, ptr);
  if(valor <= 0) return;
  foo(valor - 1);
}
int main(){
  foo(10);
  return 0;
}

La diferencia se ve en que el Stack overflow el valor va disminuyendo, sin embargo en el Heap overflow va aumentando.

Prevención

  • Aleatorización del espacio de direcciones: Reorganiza de forma aleatoria las ubicaciones del espacio de direcciones de las áreas de datos clave de un proceso, los ataques de Buffer overflow se suelen centrar en una ubicación exacta del código en cuestión, esta aleatoriedad lo hace casi imposible.

  • Prevención de la ejecución de datos: Se pueden marcar áreas de memoria como ejecutables o los que no son ejecutables, lo que también impide esta vulnerabilidad.

Última actualización