Jetons Canaries DNS¶
Les jetons Canary DNS fournissent une alerte précoce lorsqu'un payload est soumise à un bac à sable, analysée par une ingénierie inverse ou explosée dans un environnement en dehors du réseau cible. Chaque payload générée peut intégrer un domaine canari DNS unique : si le domaine est résolu à partir d'une adresse IP source inattendue, Stentor alerte tous les opérateurs connectés en temps réel via WebSocket.
Le système Canary a deux côtés : l'API d'opérateur pour l'enregistrement des canaris et l'affichage des événements de voyage, et le point de terminaison accessible par relais que le serveur DNS C2 appelle lorsqu'il observe une résolution de domaine Canary.
Comment ça marche¶
sequenceDiagram
participant Payload as Payload (Implant)
participant DNS as Relay DNS Server
participant API as Stentor API
participant DB as PostgreSQL
participant WS as Operator WebSocket
Note over Payload,WS: Payload Generation
API->>DB: Register canary (domain, payload_id, listener_id)
API->>Payload: Embed canary domain in payload
Note over Payload,WS: Canary Trip (sandbox/analyst)
Payload->>DNS: DNS query for canary domain
DNS->>API: POST /c2/canary/trip {domain, source_ip}
API->>DB: Look up canary by domain
API->>DB: Record trip event
API->>WS: Broadcast SIEM alert to all operators
API-->>DNS: {trip_id, status: "tripped"} Lorsqu'un payload est générée, Stentor enregistre un domaine Canary et l'associe à le payload et aux ID d'listener. Le domaine Canary est intégré dans le binaire de le payload. Lors de la première exécution, l'implant résout le domaine Canary via DNS. Si le serveur DNS du relais reçoit cette requête, il transmet le domaine et l'adresse IP source à l'API Stentor, qui enregistre le trajet et diffuse une alerte.
Logique de détection
Le voyage Canary lui-même ne détermine pas si l'adresse IP source appartient au réseau cible : cette évaluation est laissée à l'opérateur. L'alerte inclut l'adresse IP source, l'ID de payload et l'ID d'listener afin que l'opérateur puisse effectuer des références croisées avec l'infrastructure cible connue.
Enregistrer un Canari¶
POST /api/v1/canary/register¶
Enregistrez un domaine DNS Canary. Généralement appelé lors de la génération de le payload pour associer un domaine unique à le payload. Si le domaine existe déjà, le payload_id est mis à jour (comportement d'upsert via ON CONFLICT).
Corps de la demande :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
domain | chaîne | Oui | Le domaine Canary (par exemple, a1b2c3d4.canary.example.com) |
payload_id | chaîne | Non | UUID de le payload associée |
listener_id | chaîne | Non | UUID du listener associé |
curl -s -X POST https://stentor.app/api/v1/canary/register \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "f47ac10b.canary.ops.local",
"payload_id": "PAYLOAD_UUID",
"listener_id": "LISTENER_UUID"
}'
Réponse (201 créées) :
Événements de voyage aux Canaries¶
POST /api/v1/canary/trip (authentifié)¶
Enregistrez un événement de voyage aux Canaries. Ce point de terminaison est disponible sur l'API authentifiée pour l'enregistrement ou le test manuel des déplacements.
POST /api/v1/c2/canary/trip (accessible par relais, pas d'authentification)¶
Le serveur DNS du relais appelle ce point de terminaison lorsqu'il observe une requête DNS pour un domaine Canary enregistré. Ce point de terminaison se trouve sur le groupe de routes C2 et ne nécessite pas d'authentification JWT : il est accessible depuis le réseau interne du relais.
Corps de la demande :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
domain | chaîne | Oui | Le domaine Canary qui a été résolu |
source_ip | chaîne | Oui | Adresse IP qui a effectué la requête DNS |
curl -s -X POST https://stentor.app/api/v1/canary/trip \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "f47ac10b.canary.ops.local",
"source_ip": "198.51.100.42"
}'
Réponse (200 OK) :
{
"trip_id": "a1b2c3d4-...",
"canary_id": "c3d4e5f6-...",
"domain": "f47ac10b.canary.ops.local",
"source_ip": "198.51.100.42",
"status": "tripped"
}
Alerte WebSocket¶
Lorsqu'un canari se déclenche, une alerte SIEM est diffusée à toutes les sessions WebSocket de l'opérateur connecté. La payload de l'alerte contient :
| Champ | Type | Description |
|---|---|---|
type | chaîne | Toujours canary_trip |
domain | chaîne | Le domaine canari trippé |
source_ip | chaîne | IP de la source de la requête DNS |
canary_id | chaîne | UUID du jeton Canary |
payload_id | chaîne | UUID de le payload associée (ou unknown) |
listener_id | chaîne | UUID du listener associé (ou unknown) |
tripped_at | chaîne | Horodatage ISO 8601 |
message | chaîne | Texte d'alerte lisible par l'homme |
Domaine inconnu
Si une requête DNS arrive pour un domaine qui n'est pas enregistré en tant que Canary, l'API renvoie 404 Not Found et enregistre un avertissement. Cela peut se produire si le canari a été supprimé ou si le domaine appartient à un autre système.
Liste des Canaris¶
GET /api/v1/canary/list¶
Répertoriez tous les jetons Canari enregistrés avec leur statut de voyage. Les canaris sont renvoyés dans l'ordre chronologique inverse (le plus récent en premier).
Champs de réponse :
| Champ | Type | Description |
|---|---|---|
id | chaîne | UUID du jeton Canary |
domain | chaîne | Domaine Canari enregistré |
payload_id | chaîne | UUID du payload associé (vide si non défini) |
listener_id | chaîne | UUID du listener associé (vide s'il n'est pas défini) |
created_at | chaîne | Horodatage d'enregistrement ISO 8601 |
tripped | bool | Si le canari a été déclenché au moins une fois |
trip_count | int | Nombre total d'événements de voyage |
Exemple de réponse :
[
{
"id": "c3d4e5f6-...",
"domain": "f47ac10b.canary.ops.local",
"payload_id": "PAYLOAD_UUID",
"listener_id": "LISTENER_UUID",
"created_at": "2026-02-20T14:30:00Z",
"tripped": true,
"trip_count": 3
}
]
Liste des événements de voyage¶
GET /api/v1/canary/trips¶
Répertoriez tous les événements de voyage aux Canaries dans toutes les Canaries. Les événements sont renvoyés dans l'ordre chronologique inverse (le plus récent en premier).
Champs de réponse :
| Champ | Type | Description |
|---|---|---|
id | chaîne | UUID de l'événement de voyage |
canary_id | chaîne | UUID du canari déclenché |
domain | chaîne | Le domaine Canary qui a été résolu |
source_ip | chaîne | Adresse IP qui a effectué la requête DNS |
tripped_at | chaîne | Horodatage ISO 8601 du voyage |
Exemple de réponse :
[
{
"id": "a1b2c3d4-...",
"canary_id": "c3d4e5f6-...",
"domain": "f47ac10b.canary.ops.local",
"source_ip": "198.51.100.42",
"tripped_at": "2026-02-21T09:15:30Z"
}
]
Valeur OPSEC¶
Les canaris DNS répondent à un problème opérationnel critique : détecter quand votre payload a été capturée et analysée en dehors de l'environnement cible.
| Scénario | Comportement des Canaris |
|---|---|
| La payload a explosé sur le réseau cible | Requête DNS à partir de la plage IP attendue – aucune alerte (ou à titre informatif uniquement) |
| Payload soumise à VirusTotal | Requête DNS à partir de l'IP du bac à sable – voyages aux Canaries, opérateur alerté |
| Payload analysée par le répondeur d'incident | Requête DNS depuis le poste de travail de l'analyste – voyages aux Canaries, opérateur alerté |
| Payload transmise à l'équipe SOC/DFIR | Requête DNS du laboratoire médico-légal - voyages aux Canaries, opérateur alerté |
Réponse à le payload brûlée
Lorsqu'un canari trébuche à partir d'une source inattendue, envisagez les actions de réponse suivantes :
- Vérifiez l'adresse IP source par rapport à l'infrastructure cible connue. Des faux positifs peuvent se produire si l’organisation cible utilise des résolveurs DNS cloud ou des nœuds de sortie VPN.
- Faites pivoter le listener si le canari est associé à un listener qui peut maintenant être connu du défenseur.
- Tuez le beacon si le canari est associé à un implant spécifique qui peut être en cours d'analyse.
- Générez une nouvelle payload avec un nouveau domaine Canary pour la poursuite des opérations.
Intégration du relais DNS
Le serveur DNS C2 du relais vérifie automatiquement les requêtes DNS entrantes par rapport aux domaines Canary enregistrés. Lorsqu'une correspondance est trouvée, il appelle le point de terminaison interne POST /api/v1/c2/canary/trip (aucun JWT requis). Cela signifie que la détection Canary fonctionne de manière passive : aucune configuration supplémentaire n'est nécessaire au-delà de l'enregistrement du Canary pendant la génération de le payload.