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,