Aller au contenu

Listeners HTTP/HTTPS

HTTP et HTTPS sont les principaux transports C2 pour les opérations de Stentor. Ils fournissent une communication fiable à large bande passante qui se fond dans le trafic Web normal. HTTPS est la valeur par défaut recommandée pour tous les engagements ; HTTP ne doit être utilisé que dans des environnements de laboratoire contrôlés où la surcharge TLS n'est pas nécessaire.


Architecture

La chaîne de transport HTTP/HTTPS connecte l'implant sur la cible au backend Stentor via le relais :

sequenceDiagram
    participant Implant as Implant (Windows)
    participant Relay as Relay C2 Server (Kali)
    participant Backend as Backend API Server

    Implant->>Relay: HTTPS request (beacon check-in)
    Relay->>Backend: WebSocket event (beacon registration)
    Backend-->>Relay: WebSocket command (task queue)
    Relay-->>Implant: HTTPS response (task payload)
    Implant->>Relay: HTTPS request (task result)
    Relay->>Backend: WebSocket event (result delivery)

Le relais termine TLS et gère le protocole HTTP C2. Le backend gère l’état (registre de beacons, file d’attente des tâches) et l’interface utilisateur de l’opérateur. Toutes les interactions de l'opérateur transitent par l'API backend, qui envoie des commandes au relais via une connexion WebSocket persistante.


Création d'un listener HTTP/HTTPS

Les listeners sont créés via l'API REST et démarrent avec le statut stopped. Vous devez explicitement démarrer un listener avant qu'il n'accepte les connexions.

Créer un listener HTTPS

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS Primary",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 8443,
    "tls_auto_generate": true
  }' | jq

Créer un listener HTTP

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTP Lab",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "http",
    "port": 8080
  }' | jq

HTTP n'est pas chiffré

Les listeners HTTP transmettent le trafic C2 en texte brut. Utilisez uniquement HTTP dans des environnements de laboratoire isolés où la surveillance du réseau n'est pas une préoccupation. Pour tous les engagements de production, utilisez HTTPS.

Démarrer, arrêter et redémarrer

Après avoir créé un listener, démarrez-le pour commencer à accepter les connexions :

curl -s -X POST https://stentor.app/api/v1/listeners/$LISTENER_ID/start \
  -H "Authorization: Bearer $TOKEN" | jq '.status'
curl -s -X POST https://stentor.app/api/v1/listeners/$LISTENER_ID/stop \
  -H "Authorization: Bearer $TOKEN" | jq '.status'
curl -s -X POST https://stentor.app/api/v1/listeners/$LISTENER_ID/restart \
  -H "Authorization: Bearer $TOKEN" | jq '.status'

Cycle de vie du listener

Les listeners nouvellement créés ont toujours le statut stopped. Le point de terminaison start passe à running. Si le relais rencontre une erreur liant le port, l'état passe à error avec des détails dans le champ error_message.


Options de configuration

Le tableau ci-dessous répertorie tous les champs pertinents pour les listeners HTTP et HTTPS. Les champs marqués obligatoire doivent être fournis lors de la création d'un listener.

Champ Type Par défaut Description
name chaîne -- Obligatoire. Nom d'affichage du listener.
type chaîne -- Obligatoire. "http" ou "https".
relay_id chaîne -- Obligatoire. UUID du relais qui hébergera cet listener.
port int -- Obligatoire. Port TCP auquel le relais se lie.
bind_address chaîne "0.0.0.0" Interface réseau à lier. Utilisez "127.0.0.1" pour vous limiter à localhost.
beacon_port int null Port séparé pour la génération de payload. Lorsqu'il est défini, port est le port de liaison de relais et beacon_port est intégré aux payloads générées. Voir Séparation des ports de beacon.
tls_cert chaîne null Certificat TLS codé PEM. Utilisé uniquement lorsque type est "https".
tls_key chaîne null Clé privée TLS codée en PEM. Utilisé uniquement lorsque type est "https".
tls_auto_generate bool true Générer automatiquement un certificat auto-signé si aucun tls_cert/tls_key n'est fourni.
profile_name chaîne null Nom de profil C2 malléable pour la personnalisation du trafic HTTP.
profile_variant chaîne null Variante de profil malléable (par exemple, "jquery", "amazon").
host_rotation chaîne null Stratégie de rotation des hôtes : "round-robin", "random" ou "failover".
max_retry_strategy chaîne null Réessayez le comportement lorsque tous les hôtes échouent : "exit", "rotate" ou "sleep".
c2_hosts chaîne null Liste d'hôtes de rappel séparés par des virgules pour la rotation.
proxy_type chaîne null Protocole proxy : "http" ou "socks".
proxy_host chaîne null Nom d'hôte ou IP du serveur proxy.
proxy_port int null Port du serveur proxy.
proxy_user chaîne null Nom d'utilisateur d'authentification proxy.
proxy_pass chaîne null Mot de passe d'authentification proxy. Non renvoyé dans les réponses de l'API.
front_domains chaîne null Liste de domaines frontaux CDN séparés par des virgules pour le fronting de domaine.
guardrails JSON null Règles de filtrage des beacons. Voir Garde-corps.

Gestion des certificats TLS

Les listeners HTTPS nécessitent un certificat TLS et une clé privée. Stentor propose deux options :

Certificats générés automatiquement (par défaut)

Lorsque tls_auto_generate est true (valeur par défaut) et qu'aucun tls_cert/tls_key n'est fourni, le relais génère un certificat auto-signé au démarrage. Il s’agit du moyen le plus rapide de faire fonctionner un listener HTTPS.

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS Auto-TLS",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 443,
    "tls_auto_generate": true
  }' | jq

Certificats personnalisés

Pour les engagements de production, fournissez vos propres certificats (Let's Encrypt, autorité de certification interne ou certificats achetés). Réglez tls_auto_generate sur false et fournissez tls_cert et tls_key codés PEM :

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS Production",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 443,
    "tls_auto_generate": false,
    "tls_cert": "-----BEGIN CERTIFICATE-----\nMIID...your cert...\n-----END CERTIFICATE-----",
    "tls_key": "-----BEGIN PRIVATE KEY-----\nMIIE...your key...\n-----END PRIVATE KEY-----"
  }' | jq

Utiliser des certificats légitimes pour la production

Les certificats auto-signés déclenchent des avertissements du navigateur et sont facilement détectés par la surveillance du réseau. Pour les engagements de production, utilisez Let's Encrypt (gratuit), les certificats de l'autorité de certification interne de votre organisation ou les certificats achetés correspondant à votre domaine de couverture.


Domain fronting

Le domain fronting exploite la différence entre le nom d'hôte DNS/TLS SNI et l'en-tête HTTP Host pour acheminer le trafic C2 via un CDN, le faisant apparaître comme un trafic légitime vers le domaine du fournisseur CDN.

Comment ça marche :

  1. L'implant se connecte à un serveur Edge CDN (par exemple, cdn.cloudfront.net) via TLS
  2. Le TLS SNI affiche le domaine CDN – trafic normal
  3. L'en-tête HTTP Host à l'intérieur du tunnel TLS contient le domaine C2 réel
  4. Le CDN achemine la demande vers votre relais en fonction de l'en-tête Host

Configuration :

Définissez le champ front_domains sur une liste de domaines frontaux CDN séparés par des virgules :

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS Fronted",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 443,
    "front_domains": "d1234567.cloudfront.net,cdn.azureedge.net"
  }' | jq

Restrictions du fournisseur CDN

De nombreux fournisseurs de CDN (AWS CloudFront, Azure CDN, Google Cloud CDN) ont mis à jour leurs politiques pour empêcher le domain fronting. Testez votre configuration avant de vous y fier en production. Certains fournisseurs bloquent activement les requêtes pour lesquelles les en-têtes SNI et Host ne correspondent pas.


Configuration du proxy HTTP

Lorsque les implants fonctionnent derrière un proxy d'entreprise, configurez le listener avec des paramètres de proxy afin que les payloads générées incluent la configuration de proxy correcte :

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS via Proxy",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 443,
    "proxy_type": "http",
    "proxy_host": "proxy.corp.local",
    "proxy_port": 8080,
    "proxy_user": "svc_account",
    "proxy_pass": "proxy_password"
  }' | jq
Champ Description
proxy_type "http" pour le proxy HTTP CONNECT, "socks" pour le proxy SOCKS⅘
proxy_host Nom d'hôte ou IP du serveur proxy
proxy_port Port du serveur proxy
proxy_user Nom d'utilisateur pour l'authentification proxy (facultatif)
proxy_pass Mot de passe pour l'authentification proxy (facultatif, jamais renvoyé dans les réponses API)

Paramètres de proxy dans les payloads

La configuration du proxy est intégrée aux payloads générées. L'implant utilise ces paramètres pour acheminer tout le trafic C2 via le proxy spécifié. Ceci est essentiel dans les environnements où l’accès direct à Internet est bloqué.


Rotation des hôtes

La rotation des hôtes permet aux beacons de parcourir plusieurs adresses de rappel, améliorant ainsi la résilience si un hôte est bloqué ou tombe en panne.

Champ Description
c2_hosts Liste d'hôtes de rappel séparés par des virgules (par exemple, "c2-1.example.com,c2-2.example.com,10.0.0.50")
host_rotation Stratégie pour les hôtes cyclistes : "round-robin" (séquentiel), "random" (sélection aléatoire), "failover" (suivant en cas d'échec)
max_retry_strategy Comportement lorsque tous les hôtes échouent : "exit" (terminer le beacon), "rotate" (cycle de redémarrage), "sleep" (veille prolongée puis réessayer)

Exemple : listener HTTPS avec rotation des hôtes :

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS Resilient",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 443,
    "c2_hosts": "c2-primary.example.com,c2-backup.example.com,10.0.0.50",
    "host_rotation": "failover",
    "max_retry_strategy": "sleep"
  }' | jq

Stratégie de basculement

Utilisez "failover" avec "sleep" pour une persistance à long terme. Le beacon essaie chaque hôte dans l'ordre et, si tous échouent, se met en veille pendant une période prolongée avant de redémarrer le cycle. Cela empêche les tentatives de connexion rapides qui pourraient alerter les défenseurs.


Séparation des ports de beacon

Le champ beacon_port sépare le port auquel le relais se lie (port) du port intégré dans les payloads générées (beacon_port). Ceci est essentiel lorsqu’un proxy inverse ou un équilibreur de charge se trouve devant le relais.

Cas d'utilisation : Un proxy inverse (nginx, HAProxy) écoute sur le port 443 et transfère le trafic vers le relais sur le port 8443. Sans beacon_port, les payloads indiqueraient aux implants de se connecter au port 8443, en contournant le proxy.

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS Behind Proxy",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 8443,
    "beacon_port": 443
  }' | jq
Champ Objectif
port Où le processus de relais se lie (par exemple, 8443). Interne à l’hôte relais.
beacon_port Ce qui entre dans les payloads générées (par exemple, 443). Le port auquel les implants se connectent.

Lorsque beacon_port n'est pas défini, port sert à la fois de port de liaison et de port de rappel de payload (comportement rétrocompatible).


Garde-corps

Les garde-corps sont des règles de filtrage de beacons par listener qui limitent les beacons acceptées par le listener. Les beacons qui ne correspondent pas aux modèles de garde-corps sont rejetées lors de l'enregistrement.

Schéma JSON :

{
  "ip": "10.10.10.*",
  "hostname": "DC*",
  "username": "admin*",
  "domain": "corp.local",
  "server_name": "FILE*"
}

Tous les champs sont facultatifs. Les modèles génériques (*) sont pris en charge. Un beacon doit correspondre à tous les champs spécifiés pour être acceptée. Les champs non spécifiés ne sont pas vérifiés (acceptez n'importe quelle valeur).

Exemple : restreindre à un sous-réseau et un domaine spécifiques :

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS Scoped",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 443,
    "guardrails": {
      "ip": "10.10.10.*",
      "domain": "corp.local"
    }
  }' | jq

Tester les garde-corps avant la production

Des garde-corps trop restrictifs peuvent bloquer les beacons légitimes. Testez d'abord vos modèles dans un environnement de laboratoire. Un beacon rejetée par les garde-corps n'apparaîtra pas dans le cockpit et ne générera aucune alerte : elle est larguée silencieusement.


Hébergement de fichiers

Les listeners HTTP/HTTPS peuvent servir des fichiers arbitraires sur des URI personnalisés. Ceci est utile pour héberger des payloads, des scripts, des documents leurres ou des pages de destination directement sur le serveur C2.

Héberger un fichier

curl -s -X POST https://stentor.app/api/v1/listeners/$LISTENER_ID/host \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "uri": "/downloads/update.exe",
    "content_type": "application/octet-stream",
    "filename": "update.exe",
    "data": "TVqQAAMAAAAEAAAA..."
  }' | jq
Champ Type Description
uri chaîne Obligatoire. Chemin d'accès au fichier (doit commencer par /).
content_type chaîne Tapez MIME. Détecté automatiquement à partir de l'extension filename en cas d'omission.
filename chaîne Nom de fichier d'origine (utilisé pour la détection du type de contenu et Content-Disposition).
data chaîne Obligatoire. Contenu du fichier codé en base64.

Supprimer un fichier hébergé

curl -s -X DELETE "https://stentor.app/api/v1/listeners/$LISTENER_ID/host?uri=/downloads/update.exe" \
  -H "Authorization: Bearer $TOKEN" | jq

Restrictions d'URI

Les URI des fichiers hébergés ne peuvent pas commencer par /api/ ou /c2/ : ces préfixes sont réservés aux routes du protocole C2. Les fichiers sont servis en priorité sur le gestionnaire C2, de sorte que les URI hébergés sont prioritaires pour les chemins correspondants.


Intégration de profils malléables

Les champs profile_name et profile_variant attachent un profil C2 malléable au listener, personnalisant tous les indicateurs de trafic HTTP, y compris les URI, les en-têtes, les paramètres, l'encodage du corps et les chaînes User-Agent. Cela transforme le trafic des beacons pour imiter les applications Web légitimes (requêtes jQuery CDN, achats sur Amazon, mises à jour de Microsoft Office, etc.).

curl -s -X POST https://stentor.app/api/v1/listeners \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "HTTPS jQuery Profile",
    "relay_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "type": "https",
    "port": 443,
    "profile_name": "jquery",
    "profile_variant": "jquery"
  }' | jq

Pour une documentation complète sur la syntaxe des profils malléables, les transformations de trafic et les profils disponibles, consultez la page Profils malléables.