Satellite: sirviendo payloads "like a sir"

Satellite es un servidor que aloja payloads y que filtra las peticiones para garantizar que cada objetivo obtenga el más adecuado. Se trata de una alternativa a Apache y Nginx para alojar payloads, así como una alternativa a Caddy para la redirección de tráfico C2.

Está escrito en Go e implementa un proxy HTTP y un servidor JA3 basado en CapacitorSet, es capaz de filtrar el tráfico en función de la cantidad de veces que se ha servido un payload, tiene en cuenta los agentes de usuario, las firmas JA3, paths de prerequisitos y más.

Características destacadas

- Entrega de payloads basada en firmas JA3
- Tiempo de vida de payloads configurable
- Redirección de tráfico C2 (proxy)
- Posibilidad de "scriptear" las peticiones
- Facilidad en la captura de credenciales
- Filtrado global de peticiones

Instalación

Para probarlo en mi caso lo instalaré en Ubuntu aunque podeis encontrar instrucciones de instalación para otras plataformas en la Wiki del proyecto.  https://github.com/t94j0/satellite/wiki/Installation

Simplemente descargamos el paquete correspondiente y lo instalamos:
$ wget https://github.com/t94j0/satellite/releases/download/v0.0.1/satellite_0.0.1_linux_amd64.deb
$ sudo dpkg -i satellite_0.0.1_linux_amd64.deb

Configuración del servidor

Las rutas que Satellite buscará para cargar la configuración son las siguientes:

    $HOME/.config/satellite/config.yml
    $HOME/.satellite/config.yml
    /etc/satellite/config.yml

El fichero de config inicial es el siguiente:
erver_root: /var/www/html
listen: :443
index: /index.html
log_level: debug

server_header: Apache/2.4.1 (Unix)

geoip_path: /var/lib/satellite/GeoLite2-Country.mmdb

ssl:
  key: /etc/satellite/keys/key.pem
  cert: /etc/satellite/keys/cert.pem

Los valores de configuración son los siguientes:

Clave Configuración
server_root Server root. Por defecto en /var/www/html
listen IP:puerto a la escucha. Si no se indica ninguna IP escuchará en 0.0.0.0. Por defecto en 127.0.0.1:8080
server_header La cabecera del servidor que devolverá cuando los clientes soliciten una página
management.ip IP (o rango) permitido para ver el portal de administración
management.path Ruta URL para el servidor de administración. Si no se especifica ninguna opción la ruta no será generada.
ssl.key Ruta de la clave SSL
ssl.cert Ruta del certificado SSL
index Ruta del Index para cuando un usuario haga una petición a /
not_found.redirect Redirección a una página cuando no se encuentre la que el usuario solicita
not_found.render Ruta del fichero a rendereizar cuando no se encuentre una página
log_level Nivel de log. Las opciones son panic, fatal, error, warn, info, debug, trace

Después para la PoC simplemente crearemos un contenido de prueba:
echo "<h1>It worked!</h1>" > /var/www/html/index.html

Configuración de filtrado (sencilla PoC)

Lo siguiente que haremos será crear un filtro para ese fichero. Para ello simplentente tendremos que crearlo en la misma ubicación con el mismo nombre y extensión .info (<payload_name>.info)
echo -e "authorized_useragents:\n- ayyylmao" > /var/www/html/index.html.info

Ahora lenvantamos el servidor:
$ sudo systemctl start satellite

Y comprobamos que la petición con el agente adecuado nos devolverá el contenido:
$ curl -k -A ayyylmao https://localhost/
<h1>It worked!</h1>

Y sin embargo sin el mismo nos devolverá un "not found":
$ curl -k https://localhost/
404

Como véis esto es sólo un sencillo ejemplo, pero veamos la cantidad de opciones que tenemos disponibles:

serve

Número de veces para servir el archivo

ej.
serve: 1
Esto servirá el archivo una vez antes de que ya no se pueda acceder al archivo

authorized_useragents

Lista de cadenas de agente de usuario para permitir. Esta es una búsqueda de expresiones regulares.

ej.
authorized_useragents:
  - Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1
  - ".*Linux.*"
  - "^Moz*ll*$"

Esto permitirá todos los agentes de usuario con el string Linux, así como el agente de usuario de iPhone.

blacklist_useragents

Lista de cadenas de agente de usuario para bloquear. Esta es una búsqueda de expresiones regulares, por lo que no es necesario especificar todo el agente de usuario de forma literal.

ej.
blacklist_useragents:
  - Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1

authorized_iprange

Lista de IP o rangos de IP que pueden ver un archivo

ej.
authorized_iprange:
  - 192.168.0.1
  - 192.168.10.1/24

authorized_methods

Métodos HTTP autorizados

ej.
authorized_methods:
  - GET
  - PUT

authorized_headers

Diccionario de cabeceras que deben estar presentes

ej.
authorized_headers:
  Hacked: yes

La petición con ese header podría acceder al payload.

GET / HTTP/1.1
Host: google.com
Hacked: yes
...

authorized_ja3

Hashes JA3 autorizados para acceder al archivo. Podemos encontrar más información sobre JA3 aquí.

ej.
authorized_ja3:
  - e7d705a3286e19ea42f587b344ee6865
  - 6734f37431670b3ab4292b8f60f29984

blacklist_iprange

IPs en lista negra para acceder a un payload

ej.
blacklist_iprange:
  - 94.130.90.152

prereq

Rutas de requisitos previos que deben cumplirse, en orden, antes de que se sirva el payload.

En este caso, cuando se solicita /first, se sirve automáticamente. Cuando se accede a /second, el usuario recibirá una página 404. Cuando se accede a /first y luego se accede a /second después, /second se alojará correctamente. Cuando se accede a /first y luego a /second, finalmente podrá obtener /payload.

Ej.
first.info

second.info

prereq:
  - /first

payload.info

prereq:
  - /first
  - /second

authorized_countries

Utiliza la base de datos de países MaxMind GeoIP2 para permitir solo el acceso a países específicos. Los códigos de país ISO 3116 que se pueden usar se enumeran aquí.

Ej.
geoip:
  authorized_countries:
    - US
    - CA

blacklist_countries

Utiliza la base de datos de países MaxMind GeoIP2 para denegar el acceso a países específicos. Los códigos de país ISO 3116 que se pueden usar se enumeran aquí.

Ej.
geoip:
  blacklist_countries:
    - CA

content_type

Establece el tipo de contenido para el payload que se sirve. Puede encontrar más información sobre el header Content-Type aquí.

Ej.
content_type: application / msword

disposition

 type: attachment
  file_name: file.docx

exec

Ejecuta un programa, entrega la petición HTTP a stdin y comprueba stdout contra una variable de salida.

Ej.
exec:
  script: /home/user/test.py
  output: success

add_headers

Agrega el encabezado a todas las respuestas HTTP.

Ej.
add_headers:
  Accept-Encoding: gzip

add_headers_success

Agrega el encabezado a una respuesta HTTP si la página se alcanzó con éxito.

add_headers_failure

Agrega el encabezado a una respuesta HTTP si la solicitud fue denegada.

times_served

Número de veces que se ha accedido a un payload. Esta variable es para que Satellite pueda llevar el registro.

not_serving

Booleano para determinar si se debe servir el archivo. El servidor lo utiliza principalmente para el mantenimiento de registros, pero se puede configurar manualmente para permitir que se aloje un payload.

Ej.
not_serving: true

on_failure

Especifica qué sucede cuando la solicitud no coincide con los requisitos previos. Hay dos opciones: redirection, disponible a través de on_failure.redirect, y renderización de una página web, disponible a través de on_failure.render.

Ej.
on_failure:
  redirect: https://google.com

on_failure:
  render: /index.html

proxy

Ruta de proxy a una dirección diferente

Ej.
proxy: http://localhost:2222

credential_capture

Extrae las credenciales de la solicitud POST o PUT y las vuelca en credential_capture.file_output.

Ej.
credential_capture:
  file_output: /tmp/creds

Global Conditionals

Se puede aplicar estas configuraciones condicionales para todas las rutas utilizando el directorio de condicionales globales. De manera predeterminada, el directorio es <server_root>/conditions. Si la raíz del servidor está configurada en /etc/satellite, su directorio de condicionales globales sería /etc/satellite/condition.

Ej. Si tuvieramos una lista de agentes de usuario que se sabe que están asociados con un CIRT objetivo, así como una lista de IP asociadas con ProofPoint, entonces podríamos crear dos archivos: example_cirt_ua.yml y proofpoint_ip.yml. Ahora, podríamos compartir proofpoint_ip.yml en Twitter para que otros pueden descargarlo y usarlo con facilidad.

# /etc/satellite/conditions/proofpoint_ip.yml
blacklist_iprange:
  - 127.0.0.1
  - 127.0.0.2

# /etc/satellite/conditions/example_cirt_ua.yml
blacklist_useragents:
  - ExampleBot-CIRT

Más ejemplos

Por último, en el repositorio de Github tenéis disponible también una serie de ejemplos para que podáis ver todas las opciones arriba listadas:

https://github.com/t94j0/satellite/tree/master/examples

Cada carpeta en el directorio de ejemplos está diseñada para usarse como la raíz del servidor. Cada carpeta también proporciona un archivo README sobre lo que el ejemplo intenta explicar..

Proyecto: https://github.com/t94j0/satellite

Comentarios