¿Cómo funciona la ejecución del código arbitrario?

4

No puedo entender cómo se supone que funcionan las vulnerabilidades de ejecución de código arbitrario.

menciones de Wikipedia :

  

La ejecución de código arbitrario se logra comúnmente mediante el control sobre el puntero de instrucción de un proceso en ejecución.

Digamos que la vulnerabilidad está siendo activada por un archivo creado con fines malintencionados que dicho proceso está leyendo. ¿Cómo podría modificar el puntero de instrucción o, de lo contrario, corromper el estado interno de la aplicación para que ejecute el código del atacante?

También, dado que los sistemas operativos modernos implementan DEP y ASLR, ¿cómo es esto incluso factible? Los datos cargados desde la aplicación ni siquiera serían ejecutables, y además, también es difícil determinar el desplazamiento del shellcode / payload.

Brownie apunta por mostrar un pequeño fragmento de código que podría ser vulnerable a tal explotación.

    
pregunta user2064000 17.07.2014 - 14:05
fuente

2 respuestas

5

Cada vulnerabilidad tiene una causa específica, que a su vez conduce a formas de explotar la vulnerabilidad. Es difícil entender cómo se puede explotar algo abstracto y obtener algunos resultados abstractos, pero es mucho más fácil de entender cuando se ilustra con ejemplos. El más simple sería el clásico desbordamiento de búfer basado en pila:

void f(const char *str) {
  char buf[10];
  strcpy(buf, str);
}

Este es un ejemplo primitivo que debería ser suficiente para demostrar el problema. Supongamos que el argumento str apunta a una cadena terminada en NULL más larga que los 10 caracteres asignados para la variable en la que se está copiando. ¿Lo que sucederá? strcpy() copiará ciegamente los datos al final del búfer, sobrescribiendo lo que haya allí. Pero, ¿qué es exactamente ?

En x86, por ejemplo, la variable buf se asignaría en la pila. La pila también se usa para guardar la dirección de retorno cuando se ejecuta una instrucción CALL . Así que el diseño de la pila (simplificado) se vería así (las direcciones aumentan de arriba a abajo):

...
buf[0..3]
buf[4..7]
buf[8..9]
return address
...

Entonces, al proporcionar una cadena demasiado larga a través del argumento str , podríamos sobrescribir la dirección de retorno de f() . Si el atacante puede controlar la cadena, entonces puede controlar dónde irá el flujo de control después de que f() regrese. Esto puede ocurrir al analizar un archivo especialmente diseñado, por ejemplo.

Lo siguiente sería dirigir el control a una instrucción JMP ESP o similar en efecto, haciendo que se ejecute el código de la pila. Esta ejecución del código "directo" se evita mediante DEP.

Por supuesto, el ejemplo anterior no incluye omitir ninguna de las mitigaciones modernas (apilar canarios, SafeSEH, DEP). Esto no significa que sea globalmente imposible, pero puede ser imposible en ciertos casos. La omisión de DEP generalmente implica Programación orientada al retorno : en lugar de código, los datos especialmente diseñados se colocan en la pila. que utiliza fragmentos de funciones ya existentes en la imagen de proceso (llamadas gadgets) para ejecutar el código. Esto, a su vez, se ve atenuado por ASLR, lo que hace que las direcciones de los gadgets sean algo impredecibles. También existen técnicas para evitar ASLR.

Si desea obtener información sobre cómo explotar programas de la vida real, sugeriría tutoriales de corelanc0d3r como punto de partida.

EDIT : reemplazó la parte infractora.

    
respondido por el Dmitry Yanushkevich 17.07.2014 - 14:25
fuente
3

Inyección de código / Ejecución del código es cualquier ataque que implique engañar a un nodo en un sistema distribuido para que ejecute el código especificado en un mensaje de red que se suponía que se debía tratar como simple texto / bytes.

La parte arbitraria significa que la vulnerabilidad permite al atacante hacer uso de la autoridad completa del proceso en ejecución o de algún principio privilegiado como root .

  

Dado que los sistemas operativos modernos implementan DEP y ASLR, ¿cómo es esto incluso factible?

La inyección de código se basa en algún otro tipo de vulnerabilidad para inyectar la carga útil. Probablemente esté pensando en la inyección a través de desbordamiento de búfer pero hay otras formas de inyectar código que los trucos de espacio de direcciones de memoria no ayuda en contra.

La inyección de código no significa necesariamente inyectar instrucciones en el conjunto de instrucciones del procesador en un segmento de código / datos. Puede significar inyectar código fuente en un lenguaje de scripting que el programa interpreta tontamente . Por ejemplo, inyección de shell implica la inyección de bytes que se pasan a un shell.

  

Shell injection (o Command Injection [10]) lleva el nombre de los shells de Unix, pero se aplica a la mayoría de los sistemas que permiten que el software ejecute una línea de comando mediante programación. Las funciones típicas relacionadas con la inyección de shell incluyen system() , StartProcess() y System.Diagnostics.Process.Start() .

Algunos sistemas han utilizado tainting de cadena * para intentar mitigar las inyecciones de código que no están cubiertas por DEP / ASLR y ayuda pero no es infalible: los bits de corrupción no se serializan cuando las cadenas se serializan en archivos / Las bases de datos y, en mantenimiento, se agregan más instrucciones a un programa para corregir errores no relacionados con la seguridad de alta visibilidad que los eliminados para corregir vulnerabilidades de seguridad de baja visibilidad.

  

El concepto detrás de la comprobación de corrupción es que cualquier variable que pueda ser modificada por un usuario externo (por ejemplo, una variable establecida por un campo en un formulario web) representa un riesgo potencial para la seguridad. Si esa variable se usa en una expresión que establece una segunda variable, esa segunda variable ahora también es sospechosa. La herramienta de comprobación de manchas procede variable por variable hasta que tiene una lista completa de todas las variables que pueden verse influidas por una entrada externa.

Los sistemas que etiquetan cadenas basadas en flujo de información también se han utilizado para asegurar la distribución Los sistemas que tienen que mezclar cadenas de diferente procedencia, pero el flujo de información es más bien un enfoque de todo o nada: más difícil de adaptar a sistemas que no fueron diseñados a su alrededor.

  

El control de flujo de información protege la seguridad de la información   Al restringir cómo se transmite la información entre   Objetos y usuarios de diversas clases de seguridad. Estas clases de seguridad se expresan como etiquetas asociadas con la información o sus contenedores.

La comprobación de corrupción, arriba, es un tipo muy simple de análisis de flujo de información en el que las etiquetas están restringidas a (contaminadas, no contaminadas).

    
respondido por el Mike Samuel 17.07.2014 - 14:20
fuente

Lea otras preguntas en las etiquetas