miércoles, 30 de diciembre de 2009

Virtualización para ejecución controlada de binarios maliciosos

En mi última charla, se ha descrito la plataforma secuBT (la charla del AS/400 ha sido cancelada :-( ), orientada a la traducción de binarios para poder ejecutar código malicioso en un entorno seguro.

La plataforma utiliza traducción dinámica de código, en la que se van traduciendo los bloques de instrucciones a medida que es necesario ejecutarlas y las mete en una cache, de acuerdo al siguiente diagrama, de modo que los bloques de código sólo se traducen cuando van a ser ejecutados

Respecto a la protección, se obtiene por dos circunstancias:
  • Por un lado, todo el código traducido tiene privilegios menores que los de la librería del sistema
  • Por otro lado, todas las llamadas al sistema son chequeadas y traducidas dentro del entorno virtualizado
Para que funcione a una velocidad razonable, el programa introduce optimizaciones en la eficiencia de traducción y en la de ejecución.

Respecto a la eficiencia de traducción, tras evaluar la posibilidad de tener una traducción a código intermedio que luego se optimiza, se decidieron por la estrategia más sencilla de tener una tabla de traducción para el código, que es simple y rápida.

Respecto a la eficiencia en la ejecución, el programa introduce optimizaciones en múltiples sentidos, como ejemplo se han contado algunas de las posibles implementaciones de las llamadas indirectas (ya que todas las instrucciones que afectan al flujo de control se tratan de manera especial), para intentar disminuir su peso (la traducción estándar requiere sustituir esa única llamada por treinta instrucciones):
  • La implementación estática se traducen por una llamada con cache, de modo que se compara el destino con el anterior de esta misma llamada y si coincide no se ejecutan el resto de las comprobaciones, y su eficiencia depende de la tasa de aciertos.
  • En las llamadas dinámicas, se utiliza una tabla de hash para las direcciones "permitidas", y si se encuentra en esa tabla, tampoco se hacen todas las comprobaciones
El hecho de utilizar la traducción dinámica se traduce en la posibilidad de endurecer la seguridad con la que se ejecuta el programa:
  • Forzar la protección frente a ejecución en zonas de datos, como el heap o stack. Aunque los procesadores de Intel tienen esta funcionalidad, no todos los SO la tienen habilitada.
  • Comprobar todas las cabeceras ELF.
  • Proteger todas las estructuras de datos internas, utilizando mprotect para proteger todas las escrituras a memoria a las estructuras del entorno, salvo cuando se está ejecutando código de la propia máquina virtual.
  • Interceptar todas las llamadas al sistema, tanto para permitirla, denegarla, devolver un valor artificial o traducirla a una llamada a código de usuario que haga lo que queramos. Por ejemplo, para hacer creer al código que tiene privilegios de root (de lo cual se incluía una demo).
Todas estas medidas ofrecen protrección frente a los tres tipos más clásicos de problemas: la ejecución de código en el stack / heap que ha llegado ahí mediante un heap overflow, el retorno a libc y o la restritura de la dirección de retorno, de los cuales se ha incluido una demo en la charla.

Por último se ha presentado un estudio de las prestaciones del programa, y en media, la traducción introduce una ineficiencia de un 7%, que sólo sube a un 9% cuando se activan todas las medidas de protección de memoria y de filtrado de llamadas del sistema.

La librería se puede encontrar aquí.

No hay comentarios:

Publicar un comentario