Les ordres arrivaient par l'API
Le 12 novembre, Darktrace a montré comment une clé Claude Console volée transforme le propre Claude Code d'un développeur en implant de commande et de contrôle : les tâches arrivent dans un memory store Claude, l'agent scanne le réseau, pulvérise un mot de passe et téléverse 1 Go vers la Files API, et chaque paquet part vers api.anthropic.com. Dans Bromure Agentic Coding, la clé que l'attaquant vole est un leurre qui met la VM en pause dès qu'il sort, une clé qu'il apporte est refusée, le scan réseau est refusé sur le Mac, et chaque tâche figure dans la trace.
L'opérateur tapait chaque ordre dans un fichier texte d'un memory store Claude. Le propre Claude Code du développeur le lisait, lançait nmap et smbclient, et téléversait le butin chez Anthropic.
Le 12 novembre, Moishe Tajtelbaum et Sam Lister, chercheurs chez Darktrace Signal Labs, ont publié Living off the AI: Shared Memories as a Covert C2 Channel. C'est une démonstration en laboratoire, et Darktrace dit ne pas avoir observé la technique dans la nature. L'éditeur précise aussi qu'elle « ne repose sur aucune vulnérabilité de la plateforme Claude ». Rien ne sera corrigé. Tout est construit à partir de fonctions de Claude qui marchent comme prévu.
Le point de départ est une machine Linux sur laquelle un développeur
utilise Claude Code. Une petite charge, récupérée avec curl et
exécutée par dash, cherche l'installation de Claude Code, collecte
les identifiants API et OAuth du compte Claude Console du développeur,
et les renvoie au serveur de transit de l'attaquant avec un autre
curl.
Avec ces identifiants, l'attaquant crée un memory store, un ensemble de fichiers texte rattaché à un espace de travail Claude Console, dans un espace de travail dont le développeur est membre. Il contient trois fichiers : un battement de cœur, un fichier d'entrée pour les tâches et un fichier de sortie pour les résultats.
De retour sur la machine du développeur, la charge utilise
systemd-run pour créer un service transitoire qui relance Claude Code
en boucle. Chaque exécution se signale dans le fichier de battement de
cœur via un hook, demande à Claude Sonnet 4.5, en mode non interactif,
de lire la tâche suivante dans le fichier d'entrée, l'exécute avec des
appels d'outil bash et écrit le résultat dans le fichier de sortie.
Puis la charge s'efface. À partir de là, l'opérateur envoie chaque
ordre en langage courant, dans un fichier hébergé sur les serveurs
d'Anthropic.
Neuf tâches, une seule destination
Darktrace a lancé neuf tâches contre un réseau Active Directory simulé :
- Chercher sur le réseau local des services SSH, SMB et FTP. L'agent a
utilisé
ip,ssetncet a trouvé un serveur en 192.168.1.2. - Lancer une commande
nmapdonnée contre ce serveur. - Télécharger ce que propose le partage FTP anonyme. Il contenait des informations sur les employés et un mot de passe sans nom associé.
- Construire une liste d'identifiants à partir des noms des employés :
190 entrées dans
/tmp/usernames.txt. - Pulvériser le mot de passe sur le contrôleur de domaine via SMB. Il a fonctionné pour un compte.
- Lister avec
smbclientles partages SMB visibles par ce compte. - Lister le contenu d'un partage, dont un fichier de 1 Go.
- Télécharger ce fichier dans un dossier temporaire.
- Le découper en trois parties et les téléverser vers la Files API de Claude.
Chacun de ces ordres, chaque résultat et le téléversement de 1 Go sont
allés vers api.anthropic.com, l'hôte auquel l'agent du développeur
parle toute la journée. La plupart des entreprises qui utilisent des
agents de code ont mis cet hôte sur leurs listes d'autorisation. Le
propos de Darktrace : la liste d'autorisation est désormais le canal
C2, et l'attaquant n'a jamais eu à monter le moindre serveur après le
premier curl.
Les conseils de Darktrace en découlent. Faire passer les développeurs
des clés API à longue durée de vie à OAuth ou à une identité fédérée.
Là où c'est impossible, garder des clés de courte durée, limitées à un
seul espace de travail, et absentes des dotfiles comme de l'historique
du shell. S'assurer que la télémétrie des postes peut relier les lignes
de commande et les processus enfants d'un agent au volume de données
qu'il envoie. Surveiller les volumes de téléversement très au-dessus
du trafic d'inférence normal, et les processus d'agent qui lancent
nc, nmap ou smbclient.
Bromure Agentic Coding a été conçu autour des mêmes conseils, appliqués sur le Mac plutôt que sur le portable du développeur.
La même machine dans Bromure Agentic Coding
Bromure Agentic Coding exécute Claude Code, Codex, Grok, Kimi et omp dans des VM Ubuntu sur votre Mac, une VM par machine. L'agent, son shell et chaque programme qu'il lance restent dans cette VM. Les identifiants présents dans la VM sont des leurres. Chaque connexion sortante passe par un commutateur virtuel et un proxy sur le Mac, hors de portée de l'agent.
Donnons à l'attaquant le même point d'appui : sa charge s'exécute dans une machine Bromure, sous l'utilisateur de l'agent, et part à la recherche des identifiants de Claude Code.
La clé volée met la VM en pause
Avec une clé API Anthropic configurée, ANTHROPIC_API_KEY contient
dans la VM sk-ant-api03-brm- suivi de caractères aléatoires. Elle a
la bonne forme, donc Claude Code l'accepte, mais Anthropic ne l'a jamais
émise. La vraie clé est chiffrée sur le Mac, et le proxy ne la substitue
que dans les requêtes destinées aux hôtes d'Anthropic.
Avec un abonnement Claude, la connexion se fait sur le Mac. Le proxy répond lui-même à l'échange de jetons et garde les jetons OAuth dans le magasin de l'hôte, et Claude Code est informé que l'identifiant reste sur le Mac. Il n'y a aucun jeton OAuth dans la VM pour la charge.
Ensuite, la charge envoie sa trouvaille à son serveur de transit, et chaque requête sortante de la VM passe l'analyse du proxy. Un leurre Bromure n'a qu'une famille de destinations légitimes, et le serveur de transit n'en fait pas partie. Le proxy bloque la requête avec un HTTP 451, n'en transmet rien et met la VM en pause. Une alerte intitulée This environment may have been compromised nomme l'identifiant, l'hôte auquel il appartient et l'hôte vers lequel il a été envoyé. Shut down, le choix par défaut, arrête la machine et la marque comme compromise. L'attaque s'arrête à la première étape, avant qu'aucun memory store n'existe.
Pas de vraie clé, pas de canal
Supposons que la charge cache assez bien la clé pour la faire sortir.
L'opérateur détient désormais sk-ant-api03-brm-…. L'API d'Anthropic
la rejette. Il ne peut ni créer un memory store dans votre espace de
travail, ni y écrire une tâche, ni en lire un résultat. Le canal exige
que l'opérateur atteigne le store de son côté, et de son côté la clé ne
fonctionne pas.
L'attaquant pourrait plutôt apporter sa propre clé : une clé Anthropic d'un compte qu'il contrôle, déposée dans la VM, pour que l'implant lise les tâches dans l'espace de travail de l'attaquant. Activez Only allow credentials Bromure injects dans les Guardrails de la machine. Avec ce mode strict, toute requête qui porte un identifiant que Bromure n'y a pas mis est bloquée et déclenche la même alerte de compromission. Votre trafic Anthropic continue de fonctionner. Un second compte Anthropic dans la même VM ne passe pas.
Le scan s'arrête au Mac
Les tâches elles-mêmes ont besoin du réseau. Les machines Bromure sont
sur leur propre sous-réseau privé, et chaque paquet sortant passe par
le Mac. Passez la machine en OpenShell + Sentry et tout est refusé
sauf ce qu'une règle autorise. Les plages privées comme 192.168/16 ne
sont joignables que par un nom d'hôte exact ou une entrée
allowed_ips. La première tâche de Darktrace ne trouve rien en
192.168.1.2, nmap ne reçoit aucune réponse, et il n'y a ni partage
FTP ni contrôleur de domaine à pulvériser. Chaque connexion refusée est
une ligne Firewall dans la Security Timeline.
Avec Enforce binaries, un attestateur appartenant à root dans la VM
relie chaque connexion au programme qui l'a ouverte, et chaque règle
nomme les programmes autorisés à l'utiliser. nc, nmap et
smbclient n'y figurent nulle part. Le même mode supprime tous les
chemins vers root, donc la charge ne peut pas utiliser sudo pour le
contourner.
Les agents de la machine en sont aussi informés. Avec Tell the agent when policy blocks it, activé par défaut sur les machines OpenShell, Bromure utilise les chaînes de processus de la sentinelle noyau pour retrouver l'agent à l'origine d'une connexion bloquée et écrit une note dans sa conversation : ce qui a été bloqué, que c'est délibéré, et qu'il ne faut ni réessayer ni atteindre la même chose autrement. Une session Claude Code qu'on a convaincue de scanner le réseau reçoit cette note juste après la commande bloquée.
Le téléversement déclenche le watchdog
La dernière tâche de Darktrace envoie 1 Go à la Files API en trois parties. Le trafic normal d'un agent, ce sont des prompts, des réponses et de petits résultats d'outils. L'agent watchdog surveille chaque session depuis l'extérieur de la VM. Il compte le volume sortant au niveau du commutateur réseau, indépendamment du proxy, et le compare à la référence propre à la session. Il compte aussi les rafales de requêtes bloquées, comme un scan ou une pulvérisation de mot de passe qui se heurte au refus par défaut. Réglé sur Quarantine, il coupe le réseau de la VM et la met en pause en quelques millisecondes, puis liste ce qu'il a vu et vous demande quoi faire.
La trace montre chaque tâche
Les conseils de détection de Darktrace se résument à une corrélation : relier le processus de l'agent à ses lignes de commande, à ses enfants et aux octets qu'il envoie. Dans une machine Bromure, ces données sont déjà sur votre Mac, et l'agent ne peut pas les modifier.
Le proxy écrit un enregistrement de trace par requête : hôte, méthode,
chemin, statut, et octets de la requête et de la réponse. Un battement
de cœur toutes les quelques secondes, des lectures et écritures dans un
memory store et trois gros POST vers /v1/files ont chacun leur ligne,
avec leur taille.
Les nouvelles machines tracent au niveau AI request details, qui
conserve les corps complets des requêtes et des réponses pour Anthropic
et les autres fournisseurs de modèles, et les analyse. Dans la vue
Conversation du Trace Inspector, les tâches de l'opérateur, que
Claude a lues dans le memory store et intégrées à son contexte,
apparaissent en clair. À côté figurent les appels d'outil Bash du
modèle avec leurs commandes exactes : la ligne nmap, l'invocation de
smbclient, le split. Darktrace a dû reconstituer la chaîne à partir
de la télémétrie réseau et des postes. Ici, elle est présentée dans
l'ordre.
Sur une machine dotée de la sentinelle noyau, chaque lancement de
programme et chaque connexion sont signalés depuis le noyau de la VM,
par un canal que l'agent ne peut pas faire taire en tuant un processus.
Une connexion refusée vers 192.168.1.2 s'ouvre sur sa network
lineage : le prompt, le raisonnement de l'agent avant l'appel,
l'appel d'outil, et la chaîne de processus de claude à nmap en
passant par bash. La carte Prompt contient une tâche que vous n'avez
jamais écrite.
Faire le ménage
Si l'alerte de compromission s'est déclenchée, la machine est marquée comme compromise et ne démarrera pas tant que vous n'aurez pas choisi Wipe and Launch. Cela efface son image disque et son dossier personnel, et conserve vos jetons, vos clés SSH et vos réglages. Sans l'alerte, Reset disk reclone le disque système à partir de l'image de base. Rewind home… ramène le dossier personnel au début d'un jour antérieur, avant l'arrivée de la charge. Et comme la machine n'a jamais détenu votre vraie clé Anthropic, la clé qu'il vous faudrait sinon renouveler est restée là où elle était : sur votre Mac.
La clé est un piège
La charge trouve un leurre sk-ant-api03-brm-, ou aucun jeton avec un abonnement. L'envoyer au serveur de transit vaut un HTTP 451 et met la VM en pause.
Aucun canal à ouvrir
Un leurre ne peut ni créer ni lire un memory store. Une clé apportée par l'attaquant est refusée par le mode strict des identifiants.
Les tâches butent sur le mur
Le refus par défaut bloque 192.168.1.2, Enforce binaries ne nomme nulle part nmap ni smbclient, et Claude Code est prié de ne pas réessayer.
Chaque ordre est consigné
La trace garde le chemin et la taille de chaque requête et analyse les tâches et les appels d'outils. Le watchdog met une session en quarantaine sur un téléversement démesuré.
À faire cette semaine
- Repérez où se trouvent les clés API Claude, OpenAI et autres de vos
développeurs : profils de shell, fichiers
.env, dossiers de configuration des agents. Passez ce que vous pouvez à OAuth ou à une connexion fédérée, et rendez le reste éphémère et limité à un seul espace de travail. - Dans la Claude Console, vérifiez quels espaces de travail chaque clé peut atteindre, et cherchez-y des memory stores et des téléversements Files API que vous ne reconnaissez pas.
- Alertez sur les processus d'agent qui lancent
nc,nmap,smbclientou des outils similaires, sur les unitéssystemd-runqui lancent un agent, et sur les téléversements vers les fournisseurs de modèles très au-dessus du trafic d'inférence normal. - Ne traitez pas une entrée
api.anthropic.comdans une liste d'autorisation comme une décision de confiance sur ce qui y transite.
Donnez ensuite à vos agents une machine où la clé qu'ils détiennent ne fonctionne qu'en route vers Anthropic, où le réseau qu'ils peuvent atteindre est celui que vous avez listé, et où chaque requête qu'ils font est enregistrée là où ils ne peuvent pas la modifier. Les leurres et le mode strict sont décrits dans le chapitre Credentials & the Wire Boundary du manuel, le refus par défaut et la sentinelle noyau dans Sandbox Policy, et la trace dans Tracing & Audit.