Desbordamiento de búfer
En seguridad de la información y programación, un desbordamiento de búfer, o desbordamiento de búfer, es una anomalía en la que un programa, mientras escribe datos en un búfer, desborda el búfer's límite y sobrescribe las ubicaciones de memoria adyacentes.
Los búferes son áreas de memoria reservadas para almacenar datos, a menudo mientras se mueven de una sección de un programa a otra, o entre programas. Los desbordamientos de búfer a menudo pueden desencadenarse por entradas mal formadas; si se supone que todas las entradas serán más pequeñas que un cierto tamaño y el búfer se crea para tener ese tamaño, entonces una transacción anómala que produce más datos podría hacer que se escriba más allá del final del búfer. Si esto sobrescribe los datos adyacentes o el código ejecutable, esto puede provocar un comportamiento errático del programa, incluidos errores de acceso a la memoria, resultados incorrectos y bloqueos.
Explotar el comportamiento de un desbordamiento de búfer es una explotación de seguridad bien conocida. En muchos sistemas, el diseño de la memoria de un programa, o el sistema en su conjunto, está bien definido. Al enviar datos diseñados para provocar un desbordamiento del búfer, es posible escribir en áreas que se sabe que contienen código ejecutable y reemplazarlo con código malicioso, o sobrescribir de forma selectiva los datos relacionados con el estado del programa, provocando así un comportamiento que no era no previsto por el programador original. Los búferes están muy extendidos en el código del sistema operativo (SO), por lo que es posible realizar ataques que realicen una escalada de privilegios y obtengan acceso ilimitado a los recursos de la computadora. El famoso gusano Morris en 1988 utilizó esto como una de sus técnicas de ataque.
Los lenguajes de programación comúnmente asociados con los desbordamientos de búfer incluyen C y C++, que no brindan protección integrada contra el acceso o la sobrescritura de datos en ninguna parte de la memoria y no verifican automáticamente los datos escritos en una matriz (el tipo de búfer integrado) está dentro de los límites de esa matriz. La verificación de límites puede evitar desbordamientos de búfer, pero requiere código adicional y tiempo de procesamiento. Los sistemas operativos modernos utilizan una variedad de técnicas para combatir los desbordamientos de búfer maliciosos, en particular al aleatorizar el diseño de la memoria o dejar espacio deliberadamente entre búferes y buscar acciones que escriban en esas áreas ("canarios").
Descripción técnica
Se produce un desbordamiento del búfer cuando los datos escritos en un búfer también corrompen los valores de los datos en las direcciones de memoria adyacentes al búfer de destino debido a una verificación de límites insuficiente. Esto puede ocurrir cuando se copian datos de un búfer a otro sin comprobar primero que los datos caben en el búfer de destino.
Ejemplo
En el siguiente ejemplo expresado en C, un programa tiene dos variables que son adyacentes en la memoria: un búfer de cadena de 8 bytes de longitud, A, y un entero big-endian de dos bytes, B.
char A[8] = ";no firmado corto B = 1979;
Inicialmente, A contiene nada más que cero bytes y B contiene el número 1979.
nombre variable | A | B | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
valor | [la cuerda nula] | 1979 | ||||||||
valor hex | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 07 | BB |
Ahora, el programa intenta almacenar la cadena terminada en cero "excesivo"
con codificación ASCII en el búfer A.
strcpy()A, "excesivo");
"excesivo"
tiene 9 caracteres y codifica hasta 10 bytes, incluido el terminador nulo, pero A solo puede tomar 8 bytes. Al no verificar la longitud de la cadena, también sobrescribe el valor de B:
nombre variable | A | B | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
valor | 'e ' | 'x ' | 'c ' | 'e ' | 's ' | 's ' | 'i ' | 'v ' | 25856 | |
Hex | 65 | 78 | 63 | 65 | 73 | 73 | 69 | 76 | 65 | 00 |
El valor de B ahora se reemplazó sin darse cuenta por un número formado a partir de parte de la cadena de caracteres. En este ejemplo, "e" seguido de un byte cero se convertiría en 25856.
La escritura de datos más allá del final de la memoria asignada a veces puede ser detectada por el sistema operativo para generar un error de falla de segmentación que finaliza el proceso.
Para evitar que ocurra el desbordamiento del búfer en este ejemplo, la llamada a strcpy podría reemplazarse con strlcpy, que toma la capacidad máxima de A (incluido un nulo- carácter de terminación) como parámetro adicional y garantiza que no se escriba más de esta cantidad de datos en A:
strlcpy()A, "excesivo", tamaño()A));
Cuando está disponible, se prefiere la función de biblioteca strlcpy a strncpy, que no termina en nulo el búfer de destino si la longitud de la cadena de origen es mayor que o igual al tamaño del búfer (el tercer argumento pasado a la función), por lo tanto, A no puede terminar en nulo y no puede tratarse como una cadena de estilo C válida.
Explotación
Las técnicas para explotar una vulnerabilidad de desbordamiento de búfer varían según la arquitectura, el sistema operativo y la región de memoria. Por ejemplo, la explotación en el montón (utilizada para la memoria asignada dinámicamente) difiere notablemente de la explotación en la pila de llamadas. En general, la explotación del montón depende del administrador del montón utilizado en el sistema de destino, la explotación de la pila depende de la convención de llamada utilizada por la arquitectura y el compilador.
Explotación basada en pilas
Un usuario con inclinaciones técnicas puede explotar los desbordamientos de búfer basados en pilas para manipular el programa a su favor de una de varias maneras:
- Sobrescribiendo una variable local que se encuentra cerca del búfer vulnerable en la pila, para cambiar el comportamiento del programa
- Mediante la sobreescritura de la dirección de retorno en un marco de pila para apuntar al código seleccionado por el atacante, generalmente llamado el código de shell. Una vez que la función regrese, la ejecución se reanudará en el código del atacante.
- Por sobreescribir un puntero de función o un manipulador de excepción para apuntar al código de shell, que posteriormente se ejecuta
- Sobrescribiendo una variable local (o puntero) de un marco de pila diferente, que será utilizado por la función que posee ese marco más adelante.
El atacante diseña datos para provocar una de estas vulnerabilidades y luego coloca estos datos en un búfer proporcionado a los usuarios por el código vulnerable. Si la dirección de los datos proporcionados por el usuario utilizados para afectar el desbordamiento del búfer de pila es impredecible, explotar un desbordamiento del búfer de pila para provocar la ejecución remota de código se vuelve mucho más difícil. Una técnica que se puede utilizar para aprovechar un desbordamiento de búfer de este tipo se llama "trampolín". En esa técnica, un atacante encontrará un puntero al búfer de pila vulnerable y calculará la ubicación de su shellcode en relación con ese puntero. Luego, usarán la sobrescritura para saltar a una instrucción que ya está en la memoria, la cual hará un segundo salto, esta vez relativo al puntero; ese segundo salto ramificará la ejecución en el shellcode. Las instrucciones adecuadas a menudo están presentes en código grande. El Proyecto Metasploit, por ejemplo, mantiene una base de datos de códigos de operación adecuados, aunque enumera solo los que se encuentran en el sistema operativo Windows.
Explotación basada en montón
Un desbordamiento de búfer que ocurre en el área de datos del montón se conoce como desbordamiento del montón y se puede explotar de una manera diferente a la de los desbordamientos basados en pilas. La aplicación asigna dinámicamente la memoria en el montón en tiempo de ejecución y normalmente contiene datos de programa. La explotación se realiza al corromper estos datos de formas específicas para hacer que la aplicación sobrescriba las estructuras internas, como los punteros de listas vinculadas. La técnica de desbordamiento de montón canónico sobrescribe el enlace de asignación de memoria dinámica (como metadatos malloc) y utiliza el intercambio de puntero resultante para sobrescribir un puntero de función de programa.
La vulnerabilidad GDI+ de Microsoft en el manejo de archivos JPEG es un ejemplo del peligro que puede presentar un desbordamiento de almacenamiento dinámico.
Barreras a la explotación
La manipulación del búfer, que ocurre antes de que se lea o ejecute, puede conducir al fracaso de un intento de explotación. Estas manipulaciones pueden mitigar la amenaza de explotación, pero pueden no hacerla imposible. Las manipulaciones podrían incluir la conversión a mayúsculas o minúsculas, la eliminación de metacaracteres y el filtrado de cadenas no alfanuméricas. Sin embargo, existen técnicas para eludir estos filtros y manipulaciones; Shellcode alfanumérico, código polimórfico, código automodificable y ataques de retorno a libc. Los mismos métodos se pueden utilizar para evitar la detección por parte de los sistemas de detección de intrusos. En algunos casos, incluso cuando el código se convierte a Unicode, los reveladores han tergiversado la amenaza de la vulnerabilidad como solo una denegación de servicio cuando, de hecho, es posible la ejecución remota de código arbitrario.
Prácticas de explotación
En los exploits del mundo real, hay una variedad de desafíos que deben superarse para que los exploits funcionen de manera confiable. Estos factores incluyen bytes nulos en las direcciones, variabilidad en la ubicación del shellcode, diferencias entre entornos y varias contramedidas en funcionamiento.
Técnica trineo NOP
Un trineo NOP es la técnica más antigua y más conocida para explotar los desbordamientos del búfer de pila. Resuelve el problema de encontrar la dirección exacta del búfer aumentando efectivamente el tamaño del área objetivo. Para hacer esto, se corrompen secciones mucho más grandes de la pila con la instrucción de máquina no operativa. Al final de los datos proporcionados por el atacante, después de las instrucciones de no operación, el atacante coloca una instrucción para realizar un salto relativo a la parte superior del búfer donde se encuentra el código de shell. Esta colección de no-ops se conoce como el "trineo NOP" porque si la dirección de retorno se sobrescribe con cualquier dirección dentro de la región no operativa del búfer, la ejecución se "deslizará" baje las operaciones no operativas hasta que se redirija al código malicioso real por el salto al final. Esta técnica requiere que el atacante adivine en qué parte de la pila se encuentra el trineo NOP en lugar del shellcode comparativamente pequeño.
Debido a la popularidad de esta técnica, muchos proveedores de sistemas de prevención de intrusiones buscarán este patrón de instrucciones de máquina no operativas en un intento de detectar el shellcode en uso. Es importante tener en cuenta que un trineo NOP no contiene necesariamente solo instrucciones de máquina tradicionales no operativas; cualquier instrucción que no corrompa el estado de la máquina hasta el punto en que el shellcode no se ejecute se puede usar en lugar de la no operación asistida por hardware. Como resultado, se ha convertido en una práctica común para los creadores de exploits componer el sled no operativo con instrucciones elegidas al azar que no tendrán un efecto real en la ejecución del shellcode.
Si bien este método mejora en gran medida las posibilidades de que un ataque tenga éxito, no está exento de problemas. Los exploits que usan esta técnica aún deben confiar en cierta cantidad de suerte para adivinar las compensaciones en la pila que se encuentran dentro de la región del trineo NOP. Una suposición incorrecta generalmente provocará que el programa de destino se bloquee y podría alertar al administrador del sistema sobre las actividades del atacante. Otro problema es que el trineo NOP requiere una cantidad de memoria mucho mayor para contener un trineo NOP lo suficientemente grande como para ser útil. Esto puede ser un problema cuando el tamaño asignado del búfer afectado es demasiado pequeño y la profundidad actual de la pila es poco profunda (es decir, no hay mucho espacio desde el final del marco de la pila actual hasta el comienzo de la pila). A pesar de sus problemas, el trineo NOP suele ser el único método que funcionará para una plataforma, un entorno o una situación determinados y, como tal, sigue siendo una técnica importante.
El salto a la dirección almacenada en una técnica de registro
El "saltar al registro" La técnica permite la explotación confiable de los desbordamientos del búfer de pila sin la necesidad de espacio adicional para un trineo NOP y sin tener que adivinar las compensaciones de pila. La estrategia es sobrescribir el puntero de retorno con algo que hará que el programa salte a un puntero conocido almacenado dentro de un registro que apunte al búfer controlado y, por lo tanto, al código de shell. Por ejemplo, si el registro A contiene un puntero al inicio de un búfer, cualquier salto o llamada que tome ese registro como un operando se puede usar para controlar el flujo de ejecución.
En la práctica, un programa no puede contener intencionalmente instrucciones para saltar a un registro en particular. La solución tradicional es encontrar una instancia no intencional de un código de operación adecuado en una ubicación fija en algún lugar dentro de la memoria del programa. En la figura E de la izquierda hay un ejemplo de una instancia no intencional de la instrucción i386 jmp esp
. El código de operación para esta instrucción es FF E4
. Esta secuencia de dos bytes se puede encontrar en un desplazamiento de un byte desde el inicio de la instrucción call DbgPrint
en la dirección 0x7C941EED
. Si un atacante sobrescribe la dirección de retorno del programa con esta dirección, el programa primero saltará a 0x7C941EED
, interpretando el código de operación FF E4
como la instrucción jmp esp
y luego saltará a la parte superior de la pila y ejecutará el código del atacante.
Cuando esta técnica es posible, la gravedad de la vulnerabilidad aumenta considerablemente. Esto se debe a que la explotación funcionará de manera suficientemente confiable para automatizar un ataque con una garantía virtual de éxito cuando se ejecute. Por este motivo, esta es la técnica más utilizada en los gusanos de Internet que aprovechan las vulnerabilidades de desbordamiento del búfer de pila.
Este método también permite colocar el código shell después de la dirección de retorno sobrescrita en la plataforma Windows. Dado que los ejecutables se basan principalmente en la dirección 0x00400000
y x86 es una arquitectura Little Endian, el último byte de la dirección de retorno debe ser nulo, lo que finaliza la copia del búfer y no se escribe nada más allá de eso. Esto limita el tamaño del shellcode al tamaño del búfer, lo que puede ser demasiado restrictivo. Los archivos DLL se encuentran en memoria alta (por encima de 0x01000000
) y, por lo tanto, tienen direcciones que no contienen bytes nulos, por lo que este método puede eliminar bytes nulos (u otros caracteres no permitidos) de la dirección de retorno sobrescrita. Usado de esta manera, el método a menudo se denomina "trampolín DLL".
Contramedidas de protección
Se han utilizado varias técnicas para detectar o prevenir desbordamientos de búfer, con varias compensaciones. Las siguientes secciones describen las opciones e implementaciones disponibles.
Elección del lenguaje de programación
Assembly y C/C++ son lenguajes de programación populares que son vulnerables al desbordamiento del búfer, en parte porque permiten el acceso directo a la memoria y no están fuertemente tipados. C no proporciona protección integrada contra el acceso o la sobrescritura de datos en ninguna parte de la memoria; más específicamente, no verifica que los datos escritos en un búfer estén dentro de los límites de ese búfer. Las bibliotecas estándar de C++ brindan muchas formas de almacenar datos en búfer de forma segura, y la biblioteca de plantillas estándar (STL) de C++ proporciona contenedores que, de manera opcional, pueden realizar comprobaciones de límites si el programador solicita comprobaciones explícitamente al acceder a los datos. Por ejemplo, una función miembro vector
at()
realiza una verificación de límites y lanza una excepción out_of_range
si la verificación de límites falla. Sin embargo, C++ se comporta como C si la verificación de límites no se llama explícitamente. También existen técnicas para evitar desbordamientos de búfer para C.
Los lenguajes fuertemente tipados y que no permiten el acceso directo a la memoria, como COBOL, Java, Python y otros, evitan que se produzca un desbordamiento del búfer en la mayoría de los casos. Muchos lenguajes de programación que no sean C/C++ brindan verificación en tiempo de ejecución y, en algunos casos, incluso verificación en tiempo de compilación, lo que podría enviar una advertencia o generar una excepción cuando C o C++ sobrescribieran datos y continuaran ejecutando más instrucciones hasta que se obtengan resultados erróneos que podrían o podría no hacer que el programa se bloquee. Los ejemplos de tales lenguajes incluyen Ada, Eiffel, Lisp, Modula-2, Smalltalk, OCaml y derivados de C como Cyclone, Rust y D. Los entornos de código de bytes de Java y.NET Framework también requieren verificación de límites en todas las matrices. Casi todos los idiomas interpretados protegerán contra desbordamientos de búfer, lo que indica una condición de error bien definida. A menudo, cuando un idioma proporciona suficiente información de tipo para hacer una verificación de límites, se proporciona una opción para habilitarlo o deshabilitarlo. El análisis de código estático puede eliminar muchas verificaciones de tipos y límites dinámicos, pero las implementaciones deficientes y los casos incómodos pueden disminuir significativamente el rendimiento. Los ingenieros de software deben considerar cuidadosamente las ventajas y desventajas de la seguridad frente a los costos de rendimiento al decidir qué lenguaje y configuración de compilador utilizar.
Uso de bibliotecas seguras
El problema de los desbordamientos de búfer es común en los lenguajes C y C++ porque exponen detalles de representación de bajo nivel de búferes como contenedores para tipos de datos. Por lo tanto, se deben evitar los desbordamientos del búfer manteniendo un alto grado de corrección en el código que realiza la gestión del búfer. También se ha recomendado durante mucho tiempo evitar las funciones de biblioteca estándar que no se verifican en los límites, como gets
, scanf
y strcpy
. El gusano Morris aprovechó una llamada gets
en fingered.
Las bibliotecas de tipos de datos abstractos bien escritas y probadas que centralizan y realizan automáticamente la administración del búfer, incluida la verificación de límites, pueden reducir la ocurrencia y el impacto de los desbordamientos del búfer. Los dos principales tipos de datos de bloques de construcción en estos lenguajes en los que comúnmente ocurren desbordamientos de búfer son cadenas y matrices; por lo tanto, las bibliotecas que evitan los desbordamientos de búfer en estos tipos de datos pueden proporcionar la gran mayoría de la cobertura necesaria. Aún así, no usar correctamente estas bibliotecas seguras puede provocar desbordamientos de búfer y otras vulnerabilidades; y, naturalmente, cualquier error en la biblioteca en sí es una vulnerabilidad potencial. "Seguro" las implementaciones de la biblioteca incluyen "The Better String Library", Vstr y Erwin. La biblioteca C del sistema operativo OpenBSD proporciona las funciones strlcpy y strlcat, pero estas son más limitadas que las implementaciones de biblioteca completamente seguras.
En septiembre de 2007, se publicó el Informe técnico 24731, elaborado por el comité de estándares C; especifica un conjunto de funciones que se basan en las funciones de cadena y E/S de la biblioteca C estándar, con parámetros adicionales de tamaño de búfer. Sin embargo, la eficacia de estas funciones con el fin de reducir los desbordamientos del búfer es discutible; requiere la intervención del programador por llamada de función que es equivalente a la intervención que podría hacer que las funciones de biblioteca estándar análogas más antiguas sean seguras contra el desbordamiento del búfer.
Protección contra desbordamiento de búfer
La protección contra desbordamiento de búfer se usa para detectar los desbordamientos de búfer más comunes al verificar que la pila no haya sido alterada cuando regresa una función. Si ha sido alterado, el programa sale con un fallo de segmentación. Tres de estos sistemas son Libsafe y los parches gcc StackGuard y ProPolice.
La implementación del modo de prevención de ejecución de datos (DEP) de Microsoft protege explícitamente el puntero al controlador de excepciones estructurado (SEH) para que no se sobrescriba.
Es posible obtener una protección de pila más sólida dividiendo la pila en dos: una para datos y otra para retornos de funciones. Esta división está presente en el lenguaje Forth, aunque no fue una decisión de diseño basada en la seguridad. De todos modos, esta no es una solución completa para los desbordamientos de búfer, ya que los datos confidenciales que no sean la dirección de retorno aún pueden sobrescribirse.
Protección de puntero
Los desbordamientos de búfer funcionan mediante la manipulación de punteros, incluidas las direcciones almacenadas. PointGuard se propuso como una extensión del compilador para evitar que los atacantes puedan manipular punteros y direcciones de manera confiable. El enfoque funciona haciendo que el compilador agregue código para codificar automáticamente con XOR los punteros antes y después de que se usen. Teóricamente, debido a que el atacante no sabe qué valor se usará para codificar/decodificar el puntero, no puede predecir a qué apuntará si lo sobrescribe con un nuevo valor. PointGuard nunca se lanzó, pero Microsoft implementó un enfoque similar a partir de Windows XP SP2 y Windows Server 2003 SP1. En lugar de implementar la protección de punteros como una función automática, Microsoft agregó una rutina API a la que se puede llamar. Esto permite un mejor rendimiento (porque no se usa todo el tiempo), pero coloca la carga sobre el programador para saber cuándo es necesario.
Debido a que XOR es lineal, un atacante puede manipular un puntero codificado al sobrescribir solo los bytes inferiores de una dirección. Esto puede permitir que un ataque tenga éxito si el atacante puede intentar la explotación varias veces o puede completar un ataque haciendo que un puntero apunte a una de varias ubicaciones (como cualquier ubicación dentro de un sled NOP). Microsoft agregó una rotación aleatoria a su esquema de codificación para abordar esta debilidad de las sobrescrituras parciales.
Protección del espacio ejecutable
La protección del espacio ejecutable es un enfoque de la protección contra el desbordamiento del búfer que evita la ejecución de código en la pila o el montón. Un atacante puede usar desbordamientos de búfer para insertar código arbitrario en la memoria de un programa, pero con la protección del espacio ejecutable, cualquier intento de ejecutar ese código provocará una excepción.
Algunas CPU admiten una característica llamada bit NX ("No eXecute") o XD ("eXecute Disabled"), que, junto con el software, se puede usar para marcar páginas de datos. (como los que contienen la pila y el montón) como legibles y escribibles pero no ejecutables.
Algunos sistemas operativos Unix (por ejemplo, OpenBSD, macOS) se envían con protección de espacio ejecutable (por ejemplo, W^X). Algunos paquetes opcionales incluyen:
- PaX
- Exec Shield
- Openwall
Las variantes más recientes de Microsoft Windows también admiten la protección del espacio ejecutable, denominada prevención de ejecución de datos. Los complementos patentados incluyen:
- BufferShield
- StackDefender
La protección del espacio ejecutable generalmente no protege contra ataques de retorno a libc, o cualquier otro ataque que no dependa de la ejecución del código de los atacantes. Sin embargo, en los sistemas de 64 bits que usan ASLR, como se describe a continuación, la protección del espacio ejecutable hace que sea mucho más difícil ejecutar este tipo de ataques.
Aleatorización del diseño del espacio de direcciones
La aleatorización del diseño del espacio de direcciones (ASLR) es una función de seguridad informática que consiste en organizar las posiciones de las áreas de datos clave, que normalmente incluyen la base del ejecutable y la posición de las bibliotecas, el almacenamiento dinámico y la pila, de forma aleatoria en un proceso. espacio de dirección.
La aleatorización de las direcciones de memoria virtual en las que se pueden encontrar funciones y variables puede hacer que la explotación de un desbordamiento de búfer sea más difícil, pero no imposible. También obliga al atacante a adaptar el intento de explotación al sistema individual, lo que frustra los intentos de los gusanos de Internet. Un método similar pero menos efectivo es reorganizar procesos y bibliotecas en el espacio de direcciones virtuales.
Inspección profunda de paquetes
El uso de la inspección profunda de paquetes (DPI) puede detectar, en el perímetro de la red, intentos remotos muy básicos de explotar desbordamientos de búfer mediante el uso de firmas de ataque y heurística. Estos pueden bloquear paquetes que tienen la firma de un ataque conocido, o si se detecta una larga serie de instrucciones de no operación (conocidas como NOP-sled), estas se usaron una vez cuando la ubicación de la explotación. la carga útil es ligeramente variable.
El escaneo de paquetes no es un método eficaz, ya que solo puede prevenir ataques conocidos y hay muchas maneras de codificar un sled NOP. El shellcode utilizado por los atacantes puede convertirse en alfanumérico, metamórfico o automodificable para evadir la detección de los escáneres de paquetes heurísticos y los sistemas de detección de intrusos.
Pruebas
Comprobar los desbordamientos de búfer y parchear los errores que los provocan ayuda naturalmente a prevenir los desbordamientos de búfer. Una técnica automatizada común para descubrirlos es el fuzzing. Las pruebas de casos perimetrales también pueden descubrir desbordamientos de búfer, al igual que el análisis estático. Una vez que se detecta un posible desbordamiento de búfer, debe parchearse; esto hace que el enfoque de prueba sea útil para el software que está en desarrollo, pero menos útil para el software heredado que ya no recibe mantenimiento ni soporte.
Historia
Los desbordamientos de búfer se entendieron y se documentaron parcialmente públicamente ya en 1972, cuando el Estudio de planificación de tecnología de seguridad informática presentó la técnica: "El código que realiza esta función no verifica las direcciones de origen y destino correctamente, lo que permite que partes de el monitor para ser superpuesto por el usuario. Esto se puede usar para inyectar código en el monitor que permitirá al usuario tomar el control de la máquina." Hoy en día, el monitor se denominaría kernel.
La primera explotación hostil documentada de un desbordamiento de búfer fue en 1988. Fue una de varias vulnerabilidades utilizadas por el gusano Morris para propagarse a través de Internet. El programa explotado era un servicio en Unix llamado finger. Más tarde, en 1995, Thomas Lopatic redescubrió de forma independiente el desbordamiento del búfer y publicó sus hallazgos en la lista de correo de seguridad de Bugtraq. Un año más tarde, en 1996, Elias Levy (también conocido como Aleph One) publicó en la revista Phrack el artículo "Smashing the Stack for Fun and Profit", un paso a paso introducción a la explotación de vulnerabilidades de desbordamiento de búfer basadas en pilas.
Desde entonces, al menos dos importantes gusanos de Internet han aprovechado los desbordamientos de búfer para comprometer una gran cantidad de sistemas. En 2001, el gusano Code Red aprovechó un desbordamiento de búfer en Internet Information Services (IIS) 5.0 de Microsoft y en 2003 el gusano SQL Slammer comprometió máquinas que ejecutaban Microsoft SQL Server 2000.
En 2003, se aprovecharon los desbordamientos de búfer presentes en los juegos de Xbox con licencia para permitir que el software sin licencia, incluidos los juegos caseros, se ejecutara en la consola sin necesidad de modificaciones de hardware, conocidas como modchips. El Independence Exploit de PS2 también usó un desbordamiento de búfer para lograr lo mismo para PlayStation 2. El truco de Crepúsculo logró lo mismo con Wii, usando un desbordamiento de búfer en The Legend of Zelda: Twilight Princess.
Contenido relacionado
Flujo de bits
Memex
Enrutamiento jerárquico