domingo, septiembre 27, 2020

ATTPwn: Cómo cear tu propia implementación de una técnica MITRE ATT&CK

Después del verano seguimos sacando tiempo para ir mejorando y actualizando ATTPwn, la herramienta que publicamos en BlackHat USA y en DefCon. Se está celebrando la EkoParty 2020 en modo online, con un gran despliegue de medios y una gran cantidad de contenidos y hemos tenido la oportunidad de estar en la Eko Zone del Red Team con un workshop de ATTPwn. Ha sido un orgullo poder estar por segunda vez en EkoParty y disfrutar de los amigos, aunque en esta ocasión nos haya tocado de forma telemática.

Figura 1: ATTPwn: Cómo cear tu propia implementación de una técnica MITRE ATT&CK

Revisando un poco la documentación y los ‘To Do’ que tenemos con la herramienta me fijé que la incorporación de una implementación para alguien ajeno al desarrollo de la herramienta puede ser un poco complejo. Por ello, quería hacer un artículo explicando cómo hacer una implementación de una técnica de MITRE ATT&CK y poder añadirla a ATTPwn. En un futuro simplificaremos el proceso para que se pueda hacer desde la propia interfaz web de ATTPwn, pero a día de hoy el proceso es el que comentaremos a continuación. 


También quería recordar que el proyecto es colaborativo, por lo que cualquiera que quiere colaborar puede hacernos un pull request al repositorio de Github. Pronto iremos haciendo algunas actualizaciones diferentes del proyecto para ir añadiendo técnicas e ir añadiendo algunas funcionalidades que simplifiquen el flujo. Además, estamos estudiando algunas integraciones con ciertas herramientas que puedan dar valor a lo que se proporciona en la herramienta.

¿Por dónde empiezo?

Si queremos hacer una función implementando alguna técnica de MITRE ATT&CK deberemos optar por Powershell. En el proyecto, dentro de la carpeta ‘functions’ encontraremos un fichero llamado “skeleton file”. Este fichero es una especie de “molde” para simplificar la implementación. 

Figura 3: Fichero Skeleton

El aspecto es sencillo. Tenemos una primera parte que implementa la función en sí. El nombre de la función debe ser sustituido por ‘invoke-namefunction’, siendo namefunction el nombre que queramos. Dentro de la función se meterá todo lo necesario para llevar a cabo la técnica.


Si bajamos un poco nos encontraremos con un comentario ‘#Main program’. Este sería el programa principal. El main se divide en tres partes:

- GiveMeData: En esta parte se solicitan datos que se requieran para ejecutar nuestra función. En algunos ámbitos necesitaremos trabajar con datos como direcciones IP, nombres de usuario, hashes NTLM, etc... Por esta razón, antes de invocar nuestra función, podemos solicitar ese tipo de datos que se encuentran en el DataStore de ATTPwn.

- Execution: Tanto si requerimos de datos previos como si no, nuestra función se ejecutará. Este ocurrirá en esta parte del código. El resultado lo guardaremos en $execute. Hay que darse cuenta que $execute es un diccionario con dos campos “results” y “success”. La primera muestra el texto que se mostrará en ATTPwn como salida de la función ejecutada, mientras que ‘success’ indica si la ejecución de la función ha sido correcta o no. Esto es algo que debe ser controlado por parte del desarrollador, es algo a tener en cuenta.

- PutData:. En esta parte ‘post-ejecución’ se pueden subir datos de interés al DataStore. Esto se hace con la intención de que otras técnicas que sean ejecutadas en el mismo plan de amenaza (en la misma emulación de adversario) puedan aprovecharse de la información obtenida por esta técnica. Por ejemplo, cuando hacemos un escaneo de red y se obtienen puertos o direcciones IP (entre otros datos), se pueden volcar al DataStore a través de la llamada putData a ATTPwn.

Mi primer ejemplo

Ahora vamos a jugar con una primera técnica a la que llamaremos ‘invoke-mytechnique’, la cual implementa un ‘holamundo’. A continuación os dejo el código:

Figura 5: Primer ejemplo

Como se puede no hace uso de GiveMeData ni de PutData, ya que la técnica no requiere de información previa, ni genera información de interés a posterior, más allá de la salida que tiene y la información sobre si se ha ejecutado o no correctamente.

La función ‘invoke-mytechnique’ simplemente ejecuta un ‘holamundo’ por pantalla y almacena una palabra en $results e indica que siempre ha ido bien la ejecución de la función poniendo $good a true. Más sencilla imposible. No hace nada realmente. Ahora, voy a la carpeta functions del proyecto y veo mi función en el fichero ‘invoke-mytechnique’. Junto al resto de funciones del proyecto.

Figura 6: funcions/invoke-mytechnique

Desde el IDE me voy al fichero data.py, el cual es el que almacena todo el modelo de ATTPwn del comienzo y modifico, dentro de ‘insert_intelligence’, la línea que encaje con la táctica y la técnica que estoy implementando. Para este ejemplo, he configurado mi implementación en TA0001 y T1091, aunque no encaje con la realidad. Modifico el campo “Function =” y le pongo mi nombre de función ‘invoke-mytechnique’. 

Figura 7: Integrando la funcion

El campo de Terminated a true o false nos vale para indicar a la consola de ATTPwn si esta técnica es de escalada de privilegio o de movimiento lateral, en estos casos pensemos que si la técnica tiene éxito en su ejecución tendremos un proceso nuevo con privilegio o nuestra consola de ATTPwn se ejecutará en otra máquina.

Figura 8: Tactics TA00001 y Tecnica T1091

Ahora, vamos a probar lo que hemos hecho. Si queréis ser rápidos ejecutáis un “docker build -t attpwn:mytechnique” y levantáis una imagen de Docker con ATTPwn y vuestros cambios. Después un “docker run –rm -it -p 5000:5000 attpwn:mytechnique” y tendréis listo ATTPwn para acceder desde el navegador.  Nos vamos a la vista de Plan y pinchamos en Create a Plan. Veremos que la táctica TA0001 y la técnica T1091 (aunque se corresponde con Replication Through Removable Media, no tendrá que ver) tiene una implementación de invoke-mytechnique, tal y como se ve en la Figura 8.
  
Figura 9: Warrior P0YPMC

Cuando lanzamos un ‘warrior’ de ATTPwn en Powershell en una máquina Windows, éste se conectará y se identificará. En este caso ‘P0YPMC’ es el ID. Tras configurarle el plan ejecutará mi función invoke-mytechnique.

Figura 10: Mensaje de texto "holamundo"

Si revisamos la salida que proporciona mi función encontraremos el texto “holamundo” que es el que albergaba la variable $results y que se devolvía a la consola de ATTPwn y ésta devolvía al C2.

Usando GiveMeData y comprobando un PING

Ahora vamos a modificar la función para que haga algo más. Lo primero fijaremos el objetivo. El objetivo de la nueva función será el de hacer un PING a una o diferentes direcciones IP. Para ello introducimos algunos cambios:

- Añadimos a la función invoke-mytechnique el campo param de Powershell para recibir datos como parámetros. En este caso solo queremos recibir una dirección IP.

- La ejecución de la acción la almacenamos en $execute para que no muestre nada por pantalla en la Powershell. Comprobamos si el ping se hizo correctamente o no y almacenamos dicho valor en $good.

- Si $good marca true almacenamos el resultado como positivo y si no mostramos un resultado negativo.

Figura 11: Cambios en la función para hacer ping y devolver $good

En la imagen se puede ver el código. Fácil y sencillo.  En el caso del main, ¿Cómo evoluciona? Lo primero es indicar a dónde se realizarán las peticiones de GiveMeData. La variable $uri lo almacena. $uri = "http://"+$global:remoteip+":5000/getdata". La variable $global:remoteip es una variable global que está definida en el fichero console_template y que cuando se genera el fichero console toma valor (cuando generamos el warrior desde el C2 de ATTPwn).

Una vez sabemos dónde pedir los datos, los pedimos identificándonos con $global:id. Esta variable también se define en el fichero console y proporciona el valor del ID. Cada ID identifica a un plan de amenaza y cada plan de amenaza tiene un DataStore diferente. Esto es importante.

Figura 12: main program

Se ve que pedimos las direcciones IP al DataStore. Si quisiéramos pedir los usuarios o los hashes, en vez de ip=”” indicaríamos user, ntlm o lm. Después, ejecutamos la función invoke-mytechnique pasándole una dirección IP. Si tuviéramos más de una se lanzaría la función N veces e iríamos recogiendo los resultados para preparar la salida de ‘return @{results=$execute.results;success=$execute.success}, que es lo que le llegará a la consola y lo que se reportará al C2 de ATTPwn.

Ahora, antes de ejecutar esta función. Conectamos una consola con el C2 de ATTPwn y nos vamos a la vista ‘Results’. En esta visa vamos al DataStore de esa consola y le damos al botón ‘+’ y añadimos una dirección IP como se ve en la imagen.

Figura 13: DataStore

Ejecutamos el plan y obtenemos un resultado que podemos visualizar en ‘Results’ y pulsando sobre la lupa. El resultado es el mensaje que codificábamos cuando el PING era correcto. 

Figura 1$: Ping  OK

En el caso de que el PING no sea correcto, es decir, la máquina no responda a PING se obtiene el siguiente mensaje, tal y como se había programado en la función.

Figura 16: Mensaje final

Animamos a todos a participar en este proyecto colaborativo y que se hagan sus implementaciones de funciones. La verdad es que con la matriz de MITRE ATT&CK se puede aprender mucho sobre el Ethical Hacking y el Red Team, ya que hay un gran catálogo de técnicas que son utilizadas en el día a día. 

Saludos,
 
 Autor: Pablo González Pérez (@pablogonzalezpe), escritor de los libros "Metasploit para Pentesters", "Hacking con Metasploit: Advanced Pentesting" "Hacking Windows", "Ethical Hacking", "Got Root",  “Pentesting con Powershell”, "Pentesting con Kali Silver Edition" y de "Empire: Hacking Avanzado en el Red Team", Microsoft MVP en Seguridad y Security Researcher en el equipo de "Ideas Locas" de la unidad CDCO de Telefónica.  Para consultas puedes usar el Buzón Público para contactar con Pablo González - Conseguir 100 Tempos Gratis en MyPublicInbox

Figura 17: Contactar con Pablo González

No hay comentarios:

Publicar un comentario