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:
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:
Los valores de configuración son los siguientes:
Después para la PoC simplemente crearemos un contenido de prueba:
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)
Ahora lenvantamos el servidor:
Y comprobamos que la petición con el agente adecuado nos devolverá el contenido:
Y sin embargo sin el mismo nos devolverá un "not found":
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.
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
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
Publicar un comentario