¿cómo un retorno al sistema permite a un atacante evadir una pila no ejecutable?

4

Estoy aprendiendo sobre el retorno a los ataques de llamadas al sistema para una clase de seguridad. Entiendo que en este tipo de ataque, los atacantes reemplazan el valor de retorno estándar de un marco de pila con la dirección de una función de biblioteca. Las diapositivas de la clase dicen que esta es una forma de evadir una pila no ejecutable. ¿Cómo es eso? ¿Se ha manipulado la idea de que la función de biblioteca ha sido manipulada y, por lo tanto, cuando el marco se devuelve va al código malicioso de la biblioteca? ¿Un retorno al ataque de llamada al sistema solo es útil si la función de biblioteca ya se ha dañado?

    
pregunta bernie2436 23.02.2013 - 21:04
fuente

1 respuesta

4

Cuando una función sale, la ejecución salta a la dirección que se guardó en la pila. Las explotaciones "clásicas" de un desbordamiento de búfer alteran esa dirección guardada de modo que apunta, precisamente, a los contenidos del búfer de pila que solo se desbordó. Esto supone que el atacante elige el contenido del búfer y coloca allí el código que desea ejecutar.

Cuando la pila no es ejecutable, el exploit clásico ya no funciona. Sin embargo, el búfer aún puede llenarse y desbordarse sobre el resto de la pila, que incluye la dirección de retorno, pero también otras cosas. Considera que la pila se ve así:

address     contents
0x07fff8c8  ...
0x07fff8c4  ...
0x07fff8c0  ...
0x07fff8bc  ...
0x07fff8b8  ...
0x07fff8b4  return address
0x07fff8b0  ...
0x07fff8ac  ...
0x07fff8a8  buffer
0x07fff8a4  buffer
0x07fff8a0  buffer
(...)
0x07fff858  buffer
0x07fff854  buffer

En este diagrama aproximado, la pila crece hacia abajo (como sucede en la mayoría de las arquitecturas); las direcciones son ficticias pero realistas para una arquitectura little-endian de 32 bits en un sistema similar a Unix. El atacante intentará, al insertar datos maliciosamente creados en el búfer, obtener esta situación:

address     contents
0x07fff8c8  ...
0x07fff8c4  0
0x07fff8c0  0x07fff854
0x07fff8bc  0x07fff854
0x07fff8b8  ... 
0x07fff8b4  address of execlp()
0x07fff8b0  ...
0x07fff8ac  ...
0x07fff8a8  buffer
0x07fff8a4  buffer
0x07fff8a0  buffer
(...)
0x07fff858  0x0068732f
0x07fff854  0x6e69622f

Si el atacante puede obtener esto, entonces, cuando la función atacada regresa, el puntero de la pila se establece en 0x07fff8b4, entonces se extrae una palabra de la pila y se interpreta como la "dirección de retorno", es decir, el punto donde se ejecutará continuar. En este caso, esto hace que la CPU salte a la función de biblioteca estándar execlp() (que es una función de Unix). Esta función está, por definición, ubicada en un área de RAM que es susceptible de ejecución.

El código de execlp() espera encontrar la pila rellenada de esta manera:

address     contents
0x07fff8c8  ...
0x07fff8c4  arg2
0x07fff8c0  arg1
0x07fff8bc  arg0
0x07fff8b8  address of calling code 

execlp() interpretará arg0 como un puntero a una cadena de caracteres terminada en cero que es la ruta de un archivo ejecutable, que se ejecutará execlp() . arg1 , arg2 ... serán punteros a otras cadenas que son los argumentos que se pasarán al archivo ejecutable.

En nuestra situación, execlp() no tiene idea de cómo fue "llamado"; todo lo que sabe es que la CPU ahora lo está ingresando. Encuentra como arg0 el valor 0x07fff854 que el atacante dispuso colocar en este lugar en la pila, con su desbordamiento de búfer. Ese valor, 0x07fff854 , pasa a ser un puntero al área de RAM que anteriormente contenía el búfer, y aún contiene los datos que el atacante colocó en él porque mientras esta área está "libre", la pila aún no ha crecido. eso. En la dirección 0x07ff854 , el atacante colocó las dos palabras de 32 bits 0x6e69622f y 0x0068732f , que son la codificación de la cadena ASCII "/bin/sh" (con un 0 final).

Por lo tanto, execlp() encuentra argumentos correctamente formados que le indican que ejecute un shell, y así lo hace.

Resumen: se utiliza un desbordamiento de búfer que sobrepasa la dirección de retorno para hacer que el código atacado salte a un lugar arbitrario. El atacante desea que la CPU ejecute algún código, lo que le da cierta ventaja (por ejemplo, el código que ejecuta un shell). Como la pila no es ejecutable, el atacante no puede poner su código en la pila. Pero la biblioteca estándar es una colección de funciones que, por naturaleza, son ejecutables, y algunas pueden hacer lo que el atacante desea obtener. Entonces, es suficiente para que el atacante haga que la dirección de retorno apunte a la función de biblioteca que corresponde al efecto deseado, y se puede hacer que el mismo desbordamiento de búfer coloque en la pila los "argumentos" que la función de biblioteca utilizará, justo en el Lugar donde la función los espera. Como nada de esto usa el área de la pila como código , solo como datos , la propiedad no ejecutable de la pila no importa.

Notas :

  • No es necesario saltar al inicio de una función de biblioteca. Saltar al medio de una función también funciona. Las posibilidades son casi infinitas.

  • Las cosas funcionan de manera similar para los desbordamientos que reemplazan los punteros a las funciones, por ejemplo. vtables para objetos de C ++ en el montón. Lo que importa es que el código de la biblioteca de destino encuentre en la pila lo que espera como argumentos.

  • Las arquitecturas no x86 hacen las cosas un poco más complejas porque las convenciones de llamada para la mayoría de las arquitecturas RISC (ARM, Sparc, PowerPC, Mips ...) definen que los primeros argumentos se toman de registros convencionales, no se leen la pila. Sin embargo, el principio básico sigue siendo válido, pero significa que es más difícil hacer un código de exploit de talla única. El atacante tiene que ajustar más detalles con respecto a la aplicación exacta que ataca.

  • El atacante debe poder predecir, con buena probabilidad, dónde se cargará el código de la biblioteca en el espacio de direcciones de la aplicación. ASLR es una función de seguridad que elige la dirección de carga de forma más o menos aleatoria, precisamente para hacer que los juegos sean más difíciles para el atacante.

respondido por el Thomas Pornin 23.02.2013 - 21:51
fuente

Lea otras preguntas en las etiquetas