domingo, enero 11, 2015

Controlar el uso de Metasploit integrándolo con Latch

Las navidades dan mucho juego, y es que uno no puede estarse quieto ni en vacaciones. Un día pensando en mi querido Metasploit me pregunté, ¿Por qué la consola no tiene usuario y contraseña? ¿Por qué cuando proporcionamos un Metasploit en una organización, los pentesters pueden lanzarlo todo? Aún recuerdo una auditoría donde uno de nuestros clientes nos pidió expresamente que no se lanzara un determinado exploit en su red, ya que ellos tenían constancia ese bug y lo tenían controlado, pero el pentester lo lanzó, ganándonos mi jefe y yo una bronca por un descuido innecesario.

Figura 1: Cómo controlar el uso de Metasploit integrándolo con Latch

Pensé que teniendo a mano el SDK de Latch para Ruby sería sencillo ver dónde integrar una protección como Latch en Metasploit, y como vais a ver, así fue. Lástima que como empleado no me pudiera presentar al Latch Plugin Contest, porque creo que hubiera tenido alguna posibilidad con esta idea de alcanzar algún premio.

Elección del punto de Integración de Latch en Metasploit

En primer lugar, mi intención era verificar que podía latchear Metasploit y estudié la función exploit que viene en los módulos de dicho tipo. Si observamos el número de módulos que existen de tipo exploit hoy día en el framework, nos hace entender que no es viable modificar entre 900 y 1400 módulos con el fin de que la función exploit haga peticiones a Latch para comprobar el estado del pestillo. Podría ser un objetivo para bloquear un determinado exploit concreto en un determinado momento, pero para hacerlo más o menos de forma genérica no es una buena opción, así que una vez descartada esta idea pensé que se debía ir un paso más arriba.

Si nos dirigimos a la ruta de instalación de Metasploit y listamos el contenido de la carpeta lib podemos encontrar una carpeta denominada core la cual debería contener la carpeta exploit y el fichero exploit.rb. La carpeta contiene subcategorías de los módulos de tipo exploit, como pueden ser los fileformat, los client-side o los locales, típicos de elevación de privilegios. Si estudiamos el código del fichero exploit.rb podemos localizar la función initialize, pero antes de entrar en detalle hay que tener claro que todo módulo de Metasploit de tipo exploit hereda de la clase exploit.rb, por lo que si conseguir configurar Latch en este punto estaremos controlando la ejecución de todos los módulos que heredan de éste, en otras palabras, todos los módulos de tipo exploit.

Creación de la applicación en Latch

Una vez decidido que el lugar donde realizar la integración en Metasploit para consultar Latch, el siguiente paso es crearse la aplicación Latch que va a representar a mi framework. Para ello vamos al Área de Desarrolladores de Latch y creamos una nueva aplicación. Yo la he llamado Pablo's Metasploit y he creado tres operaciones en ella para controlar el estado de auxilary, console y exploit de forma independiente, que voy a ir probando a lo largo del artículo.

Figura 2: Creación de la aplicación Latch para Metasploit en el Área de Desarrolladores de Latch

Como hemos visto antes, si hacemos que se realicen consultas a Latch en la función initialize de exploit.rb estaremos logrando que cuando se cree una instancia de un módulo de este tipo, primero se compruebe el estado del cerrojo antes que nada. Antes de ponerme a probarlo decidí crearme una clase a la cual denominé LatchMsf. Esta clase dispone de los métodos y atributos necesarios para crear un objeto que compruebe el estado de la operación pertinente. Para crear esta clase hice uso del SDK de Latch para Ruby, el cual simplifica el uso de las peticiones a la API.

Para esta prueba se ha colocado en el propio código LatchMsf.rb todo lo necesario como es el AppID y el Secret que se obtienen en el Área de desarrolladores de Latch, el AccountID que se obtiene una vez que el usuario se parea con Latch, y las operaciones en caso de haberlas que se creen en la zona de crear la aplicación Latch. Además, se puede visualizar en la imagen anterior la función initialize que es la que se ejecuta cuando creamos el objeto. En este caso, no se ha implementado ninguna acción.

Figura 3: AppID, Secret, AccountID y Operaciones de Latch en la función initialize

Para poder probar los controles creados, el primer paso necesario es parearnos con nuestra cuenta de usuario de Latch desde Metasploit para tener el Account ID de la cuenta que va a controlar el estado de las operaciones que se ve en la Figura 3.  El SDK de Latch para Ruby proporciona una función sencilla de utilizar, pero viendo que deberíamos utilizar diferentes funciones decidí implementar un mini cliente para Latch en Ruby, al cual se denominó manage_latch_msf.

Cliente de Latch en Ruby: Manage Latch MSF

Este pequeño cliente tiene como objetivo facilitar mi uso de Latch con Metasploit a través de Ruby. Lo primero fue ver qué requisitos tendría en mi implementación de Latch para Metasploit, dándome cuenta de que necesitaría parearme y desparearme, comprobar el estado global del Latch, listar operaciones, comprobar el estado de las operaciones, crear, actualizar y eliminar operaciones de manera ágil, por eso este pequeño cliente. En la siguiente imagen se puede visualizar lo que necesitamos al comenzar, que son el AppID y el Secret. La función showMenu lo que hace es mostrar por pantalla el menú de la aplicación con las distintas opciones.

Figura 4: Función showMenu en Manage Latch MSF para gestionar Latch en Metasploit

La función pair y unpair son prácticamente la petición que se hace desde el SDK, salvando que me solicita el token en el caso del pair. La función globalStatus comprueba el estado global de Latch para un AccountID, para lo que ya deberíamos estar pareados. Hay que tener en cuenta que en el momento de realizar el pair estaremos obteniendo un objeto respuesta que contiene data o errors en función de cómo haya ido la petición. Habría que controlar, por ejemplo con rescue la posibilidad de capturar errores en el código. Para listar operaciones utilizamos la llamada getOperations del SDK, salvo que no se le pasa como argumento el AccountID, si no que se pasa el Parent OP. El Parent OP es la operación padre de las que cuelgan el resto de operaciones.

Figura 5: Implementación de funciones básicas de pareo, despareo y comprobación de estado

Manejar el SDK de Latch en cualquier lenguaje para parear, desparear y consultar los estados es bastante sencillo y se aprende en muy poco tiempo, pero si es tu primera vez, lo más recomendable es que te veas alguna de las charlas de una hora de cómo integrar Latch en aplicaciones PHP, Latch en aplicaciones Java o Latch en aplicaciones .NET.

Continuando con Manage Latch MSF tenemos más funciones para el tratamiento de las operaciones, como son operationStatus la cual solicita al usuario que introduzca la operación para, posteriormente, utilizar la función del SDK operationStatus pasándole el AccountID y la operación que el usuario ha introducido. La función createOperation solicita al usuario que introduzca el nombre de la nueva operación e invoca a la función createOperation del SDK pasándole el AppID, el nombre que introdujo el usuario, y el estado del two factor y el lockOnRequest, es decir, si habrá segundo factor de autenticación con OTP y si el usuario podrá configurar que tras la petición de estado se cierre Latch - es decir, que el Latch abierto se cierre cada vez que se acceda -.

Figura 6: Comprobación de estado de operación y creación de operación

Por último quedaban las funciones de actualización y eliminación de operación. En ambos casos se solicita al usuario que introduzca el OperationID. En el caso de updateOperation se ejecuta la instrucción api.updateOperation pasándole como argumentos la operación introducida por el usuario, el nombre nuevo que se quiere configurar para la operación, y los estados del two factor y el Lock on Request. Para eliminar la operación, y tras solicitar el OperationID al usuario se ejecuta la instrucción api.deleteOperation pasándole la operación que introdujo el usuario.

Figura 7: Funciones para actualización y eliminación de operaciones

Por último queda, lo que llamaríamos Programa Principal. Lo primero que hacemos al arrancar el programa es utilizar el SDK de Latch para Ruby para crearnos un objeto, al cual denominamos api mediante la instrucción Latch.new(APPID, SECRET). Tanto APPID como SECRET son variables que se encuentran en el archivo, pero que podrían ser leídas de un fichero. Posteriormente mostramos el menú y solicitamos al usuario que introduzca una opción. En función del número o carácter introducido por el usuario se ejecutará una función u otra de las definidas anteriormente.

Figura 8: Programa Principal

A continuación se muestra un ejemplo de ejecución de Manage Latch MSF, en el cual se puede ver cómo se comprueba el estado global de Latch, el listado de operaciones o la comprobación del estado de una operación.

Figura 9: Ejecución del mini cliente para Latch en Ruby

Go back to… LatchMsf

Volviendo al código de LatchMsf, y habiendo solo hablado de la función initialize, decir que consta de varias funciones como son:
• checkExploit()
• checkAuxiliary()
• checkPayload()
• checkConsole()
Estas funciones son exactamente iguales, solo que depende de la operación asignada, es decir, para controlar los cuatro módulos habremos tenido que crear cuatro operaciones -una más de las creadas originalmente - , llamadas por ejemplo exploit, auxiliary, payload y console, y habremos almacenado en LatchMsf esos valores de OperationID. Podríamos disponer de una única función la cual reciba la operación a consultar. Por continuar con el archivo exploit.rb, mostraré la función checkExploit() la cual utiliza el OperationID que se crearía para dicho tipo de módulos.

Figura 10: Función que chequea el estado de la operación Exploit

Vale, sencillo, ¿no?, pero ¿desde qué parte de Metasploit realizamos las peticiones? Dentro del archivo exploit.rb, en la función initialize, la cual sabemos que siempre será ejecutada cuando carguemos o ejecutemos un módulo de tipo exploit en Metasploit, debe ser la que cree un objeto de tipo LatchMsf y ejecute el método checkExploit.

Además debemos incluir require [ruta LatchMsf] junto a los demás require que tenga el código del fichero. De este modo podremos crear nuestro objeto LatchMsf. Se observa que son 4 líneas de código lo que necesitamos introducir en Metasploit para proteger nuestros módulos de tipo exploit. En el caso de los módulos de tipo auxiliary o payload ocurre exactamente igual, deberíamos ir al fichero auxiliary.rb y/o payload.rb, que se encuentran en la misma ruta que exploit.rb, y añadir las 4 líneas de código en la función initialize. Sólo hay que ejecutar los métodos checkAuxiliary y checkPayload en vez de checkExploit.

Figura 11: Inserción de código en exploit.rb

En el caso de querer poner Latch la consola de Metasploit para que lo primero que se realice sea la comprobación, tenemos que buscar uno de los archivos de interacción de usuario con el framework. Para ello nos dirigimos a la ruta lib/msf/ui dentro de la carpeta dónde se encuentre Metasploit. En esta carpeta existe un fichero denominado driver.rb, que investigando un poco podemos ver como al ejecutar la consola de Metasploit se utiliza la función initialize. Esto es fácilmente comprobable, simplemente poniendo un puts “hola mundo” en el cuerpo de la función initialize, lograremos verlo impreso por pantalla al arrancar la consola.

Figura 12: Código para comprobar Latch en el arranque de la consola

Prueba de Concepto: Probando los latches

Antes de nada vamos a ver como tenemos configurada la aplicación de Metasploit en nuestra app de Latch después de haber realizado el proceso de pareado con Manage Latch MSF. En la imagen se pueden visualizar diversas aplicaciones y servicios protegidos con Latch, y uno denominado Pablo’s Metasploit. Podemos bloquear todas las operaciones, realizando un bloqueo global, pero si pinchamos sobre la aplicación accedemos a una subvista dónde se muestran las diversas operaciones configuradas, para esta prueba de concepto una operación para bloquear la utilización de los módulos exploit, otra para la ejecución de módulos auxiliary y una última operación para la utilización de la propia consola.

Figura 13: Mi Metasploit en mi Latch

Cuando arrancamos la consola de Metasploit y antes hemos activado el Latch en la operación referente a la consola se mostrará el texto “verifying Latch…”, si el pestillo está activo se avisará al usuario que Latch se encuentra cerrado y se terminará la ejecución de la consola, no pudiendo acceder al uso de Metasploit. Por supuesto, se recibirá una alerta en la app de Latch informando del intento de acceso cuando estaba bloqueada.

Figura 14: Consola de Metasploit protegida con Latch y Bloqueada

Ahora habilitamos la operación para que se pueda entrar a la consola, pero cerramos la operación de uso de los módulos de tipo exploit. En la siguiente imagen se puede ver como accedemos a la consola de Metasploit, pero cuando intentamos acceder mediante el comando use exploit/multi/handler no podemos acceder a dicho modulo. En el caso de que intentemos acceder a un módulo, por ejemplo, de tipo auxiliary podemos acceder sin problema ya que la operación para este tipo de módulos se encuentra abierta.

Figura 15: Bloqueo del uso de los módulos de tipo exploit

Por último, en el caso de que la operación de acceso a módulos de tipo exploit se encontrase abierta y el usuario accediera con el comando use a un módulo de este tipo, se podría bloquear el lanzamiento cuando se ejecutase exploit si decidimos cerrar la operación cuando el módulo se encuentra cargado. Como se puede ver en la imagen tenemos el módulo exploit/multi/handler cargado, pero en ese instante cerramos la operación desde Latch, por lo que cuando el usuario ejecute el comando exploit para lanzar el módulo, éste comprobaría el estado del Latch, provocando la no ejecución del módulo.

Figura 16: Bloqueo de la instrucción exploit

Conclusiones

Está claro que esta medida puede ser una buena prevención para que la gente de tu equipo no realice acciones que no debiera. Lanzar un exploit es algo que debe estar controlado en un entorno de producción, y saberse las repercusiones que dicho exploit tiene en el sistema sobre el que se lanza, por lo que cuanto mayor control tengamos mejor. Como anécdota contar que durante el desarrollo de alguna auditoría yo he sufrido en mis carnes como alguno de mis compañeros realizaba acciones que no debían, por lo que con este tipo de medidas podríamos evitar más de un coscorrón o bronca al equipo.

Además, aprovechando la opción de Latch de avisar cuando se ejecuta una operación aunque esté abierta, se podría monitorizar el uso que se está realizando de cada una de las máquinas. Por supuesto, si el usuario que maneja Metasploit decide manipular por sí mismo el código y anular la integración de Latch, no se podrá hacer nada, pero si lo que se quiere es utilizar Latch como forma de autoregulación y control de un equipo, es más que útil.

Autor: Pablo González Pérez (@pablogonzalezpe)
Escritor de los libros "Metasploit para Pentesters" y "Ethical Hacking"

2 comentarios:

Anónimo dijo...

Wtf....

Anónimo dijo...

¿Para cuando integrareis latch con el acceso a mi nevera?

Es broma, estais haciendo un gran trabajo, ojala mas apps en el futuro funcionen bien con latch, es un segundo factor muy bien pensado.

Entrada destacada

Tu Latch "Hack Your Innovation Contest": Haz un PoC & Hack por 1.000 €

El pasado Telefónica Innovation Day 2024 lanzamos oficialmente el " Tu Latch Hack Your Innovation Contest " en el que repartimos ...

Entradas populares