Las órdenes llegaban por la API
El 12 de noviembre, Darktrace mostró cómo una clave robada de Claude Console convierte el propio Claude Code de un desarrollador en un implante de comando y control: los trabajos llegan a un memory store de Claude, el agente escanea la red, prueba una contraseña contra todas las cuentas y sube 1 GB a la Files API, y cada paquete va a api.anthropic.com. En Bromure Agentic Coding, la clave que roba el atacante es un sustituto que pausa la VM al salir, una clave que traiga él se rechaza, el escaneo de red se rechaza en el Mac y cada trabajo queda en la traza.
El operador escribía cada orden en un archivo de texto dentro de un memory store de Claude. El propio Claude Code del desarrollador lo leía, ejecutaba nmap y smbclient, y subía el botín a Anthropic.
El 12 de noviembre, Moishe Tajtelbaum y Sam Lister, investigadores de Darktrace Signal Labs, publicaron Living off the AI: Shared Memories as a Covert C2 Channel. Es una demostración de laboratorio, y Darktrace dice que no ha visto la técnica en uso real. También dice que la técnica no depende de ninguna vulnerabilidad de la plataforma Claude. No habrá parche. Está hecha con funciones de Claude que funcionan tal como se diseñaron.
El punto de partida es una máquina Linux donde un desarrollador usa
Claude Code. Una pequeña carga, descargada con curl y ejecutada por
dash, busca la instalación de Claude Code, recoge las credenciales de
API y OAuth de la cuenta de Claude Console del desarrollador y las
envía al servidor de preparación del atacante con otro curl.
Con esas credenciales, el atacante crea un memory store, un conjunto de archivos de texto vinculado a un espacio de trabajo de Claude Console, en un espacio de trabajo al que pertenece el desarrollador. Contiene tres archivos: un latido, un archivo de entrada para los trabajos y un archivo de salida para los resultados.
De vuelta en la máquina del desarrollador, la carga usa systemd-run
para crear un servicio transitorio que lanza Claude Code una y otra
vez. Cada ejecución se reporta en el archivo de latido mediante un
hook, pide a Claude Sonnet 4.5, en modo no interactivo, que lea el
siguiente trabajo del archivo de entrada, lo lleva a cabo con llamadas
a la herramienta bash y escribe el resultado en el archivo de salida.
Luego la carga se borra a sí misma. A partir de ahí, el operador envía
cada orden en lenguaje corriente a un archivo en los servidores de
Anthropic.
Nueve trabajos, un solo destino
Darktrace ejecutó nueve trabajos contra una red de Active Directory simulada:
- Buscar en la red local SSH, SMB y FTP. El agente usó
ip,ssyncy encontró un servidor en 192.168.1.2. - Ejecutar un comando
nmapconcreto contra ese servidor. - Descargar lo que ofrece el recurso FTP anónimo. Contenía datos de empleados y una contraseña sin nombre asociado.
- Armar una lista de usuarios con los nombres de los empleados: 190
entradas en
/tmp/usernames.txt. - Probar la contraseña contra todas las cuentas en el controlador de dominio por SMB. Funcionó con una.
- Listar con
smbclientlos recursos SMB que ve esa cuenta. - Listar el contenido de un recurso, que incluía un archivo de 1 GB.
- Descargar ese archivo a una carpeta temporal.
- Dividirlo en tres partes y subirlas a la Files API de Claude.
Cada una de esas órdenes, cada resultado y la subida de 1 GB fueron a
api.anthropic.com, el mismo host con el que el agente del
desarrollador habla todo el día. La mayoría de las empresas que usan
agentes de código han puesto ese host en sus listas de permitidos. El
argumento de Darktrace es que la lista de permitidos es ahora el canal
C2, y el atacante nunca tuvo que montar un servidor propio después del
primer curl.
Los consejos de Darktrace se desprenden de ahí. Pasar a los
desarrolladores de claves de API de larga duración a OAuth o identidad
federada. Donde no se pueda, mantener las claves de corta duración,
limitadas a un espacio de trabajo y fuera de los dotfiles y del
historial del shell. Asegurarse de que la telemetría de los equipos
pueda vincular las líneas de comando y los procesos hijos de un agente
con la cantidad de datos que envía. Vigilar volúmenes de subida muy por
encima del tráfico de inferencia normal, y procesos de agente que
ejecuten nc, nmap o smbclient.
Bromure Agentic Coding se construyó en torno a esos mismos consejos, aplicados en el Mac en lugar de en el portátil del desarrollador.
La misma máquina en Bromure Agentic Coding
Bromure Agentic Coding ejecuta Claude Code, Codex, Grok, Kimi y omp en VM Ubuntu en tu Mac, una VM por máquina. El agente, su shell y cada programa que inicia se quedan dentro de esa VM. Las credenciales de la VM son sustitutos. Cada conexión saliente pasa por un switch virtual y un proxy en el Mac, fuera del alcance del agente.
Démosle al atacante el mismo punto de apoyo: su carga se ejecuta dentro de una máquina Bromure, como el usuario del agente, y va a buscar las credenciales de Claude Code.
La clave que roba pausa la VM
Con una clave de API de Anthropic configurada, ANTHROPIC_API_KEY en
la VM contiene sk-ant-api03-brm- seguido de caracteres aleatorios.
Tiene la forma correcta, así que Claude Code la acepta, pero Anthropic
nunca la emitió. La clave real está cifrada en el Mac, y el proxy la
coloca solo en las solicitudes dirigidas a los hosts de Anthropic.
Con una suscripción a Claude, el inicio de sesión ocurre en el Mac. El proxy responde él mismo al intercambio de tokens y guarda los tokens OAuth en el almacén del host, y a Claude Code se le indica que la credencial se queda en el Mac. No hay tokens OAuth en la VM que la carga pueda recoger.
Después, la carga envía lo que encontró a su servidor de preparación, y cada solicitud saliente de la VM pasa por el análisis del proxy. Un sustituto de Bromure tiene una sola familia de destinos legítimos, y el servidor de preparación no está en ella. El proxy bloquea la solicitud con HTTP 451, no reenvía nada y pausa la VM. Una alerta titulada This environment may have been compromised nombra la credencial, el host al que pertenece y el host al que se envió. Shut down, la opción por defecto, detiene la máquina y la marca como comprometida. El ataque se detiene en el primer paso, antes de que exista ningún memory store.
Sin clave real, no hay canal
Supón que la carga esconde la clave lo bastante bien como para sacarla.
El operador tiene ahora sk-ant-api03-brm-…. La API de Anthropic la
rechaza. No puede crear un memory store en tu espacio de trabajo,
escribir un trabajo en él ni leer un resultado. El canal exige que el
operador llegue al store desde su lado, y desde su lado la clave no
funciona.
El atacante podría traer una clave propia: una clave de Anthropic de una cuenta que controla, dejada en la VM, para que el implante lea los trabajos del espacio de trabajo del atacante. Activa Only allow credentials Bromure injects en los Guardrails de la máquina. Con este modo estricto, cualquier solicitud que lleve una credencial que Bromure no puso se bloquea y lanza la misma alerta de compromiso. Tu tráfico de Anthropic sigue funcionando. Una segunda cuenta de Anthropic en la misma VM no pasa.
El escaneo se detiene en el Mac
Los propios trabajos necesitan la red. Las máquinas Bromure están en su
propia subred privada, y cada paquete saliente pasa por el Mac. Cambia
la máquina a OpenShell + Sentry y todo se deniega salvo lo que una
regla permita. Los rangos privados como 192.168/16 solo son accesibles
mediante un nombre de host exacto o una entrada allowed_ips. El
primer trabajo de Darktrace no encuentra nada en 192.168.1.2, nmap no
recibe respuesta, y no hay recurso FTP ni controlador de dominio contra
el que probar contraseñas. Cada conexión rechazada es una fila
Firewall en la Security Timeline.
Con Enforce binaries activado, un atestador propiedad de root en la
VM vincula cada conexión con el programa que la abrió, y cada regla
nombra los programas que pueden usarla. nc, nmap y smbclient no
aparecen en ninguna. El mismo modo elimina todos los caminos a root,
así que la carga no puede usar sudo para esquivarlo.
Los agentes de la máquina también se enteran. Con Tell the agent when policy blocks it, activado por defecto en las máquinas OpenShell, Bromure usa las cadenas de procesos del centinela del kernel para encontrar al agente detrás de una conexión bloqueada y escribe una nota en su conversación: qué se bloqueó, que es deliberado y que no debe reintentarlo ni llegar a lo mismo por otra vía. Una sesión de Claude Code a la que convencieron de escanear la red recibe esa nota justo después del comando bloqueado.
La subida dispara el watchdog
El último trabajo de Darktrace envía 1 GB a la Files API en tres partes. El tráfico normal de un agente son prompts, respuestas y resultados de herramientas pequeños. El agent watchdog vigila cada sesión desde fuera de la VM. Cuenta el volumen saliente en el switch de red, por separado del proxy, y lo compara con la línea base de la propia sesión. También cuenta ráfagas de solicitudes bloqueadas, como un escaneo o una prueba masiva de contraseñas que choca con la denegación por defecto. Configurado en Quarantine, corta la red de la VM y la pausa en milisegundos, luego enumera lo que vio y te pregunta qué hacer.
La traza muestra cada trabajo
Los consejos de detección de Darktrace se reducen a correlación: vincular el proceso del agente con sus líneas de comando, sus hijos y los bytes que envía. En una máquina Bromure esos registros ya están en tu Mac, y el agente no puede editarlos.
El proxy escribe un registro de traza por solicitud: host, método,
ruta, estado y bytes de solicitud y respuesta. Un latido cada pocos
segundos, lecturas y escrituras en un memory store y tres POST grandes
a /v1/files tienen cada uno su propia fila, con su tamaño.
Las máquinas nuevas trazan en el nivel AI request details, que
guarda los cuerpos completos de solicitudes y respuestas de Anthropic y
de los demás proveedores de modelos, y los analiza. En la vista
Conversation del Trace Inspector, los trabajos del operador, que
Claude leyó del memory store y metió en su contexto, aparecen en texto
claro. Junto a ellos están las llamadas a la herramienta Bash del
modelo con sus comandos exactos: la línea de nmap, la invocación de
smbclient, el split. Darktrace tuvo que reconstruir la cadena a
partir de telemetría de red y de equipos. Aquí aparece en orden.
En una máquina con el centinela del kernel, cada inicio de programa
y cada conexión se reportan desde dentro del kernel de la VM, por un
canal que el agente no puede silenciar matando un proceso. Una conexión
rechazada a 192.168.1.2 se abre en su network lineage: el prompt,
el razonamiento del agente antes de la llamada, la llamada a la
herramienta y la cadena de procesos de claude a nmap pasando por
bash. La tarjeta Prompt contiene un trabajo que tú nunca escribiste.
Limpieza
Si saltó la alerta de compromiso, la máquina queda marcada como comprometida y no arrancará hasta que elijas Wipe and Launch. Eso borra su imagen de disco y su carpeta personal y conserva tus tokens, claves SSH y ajustes. Sin la alerta, Reset disk vuelve a clonar el disco del sistema desde la imagen base. Rewind home… devuelve la carpeta personal al inicio de un día anterior, antes de que llegara la carga. Y como la máquina nunca tuvo tu clave real de Anthropic, la clave que de otro modo tendrías que rotar se queda donde estaba: en tu Mac.
La clave es una trampa
La carga encuentra un sustituto sk-ant-api03-brm-, o ningún token con una suscripción. Enviarlo al servidor de preparación da HTTP 451 y pausa la VM.
Ningún canal que abrir
Un sustituto no puede crear ni leer un memory store. Una clave que trae el atacante la rechaza el modo estricto de credenciales.
Los trabajos chocan con el muro
La denegación por defecto rechaza 192.168.1.2, Enforce binaries no nombra nmap ni smbclient en ningún sitio, y a Claude Code se le dice que no reintente.
Cada orden queda registrada
La traza guarda la ruta y el tamaño de cada solicitud y analiza los trabajos y las llamadas a herramientas. El watchdog pone en cuarentena una sesión ante una subida desmesurada.
Qué hacer esta semana
- Averigua dónde están las claves de API de Claude, OpenAI y otros
modelos de tus desarrolladores: perfiles del shell, archivos
.env, carpetas de configuración de agentes. Pasa lo que puedas a OAuth o a inicio de sesión federado, y haz que el resto sea de corta duración y limitado a un espacio de trabajo. - En Claude Console, revisa a qué espacios de trabajo llega cada clave y busca en ellos memory stores y subidas a la Files API que no reconozcas.
- Alerta sobre procesos de agente que inicien
nc,nmap,smbcliento herramientas parecidas, sobre unidadessystemd-runque lancen un agente y sobre subidas a proveedores de modelos muy por encima del tráfico de inferencia normal. - No trates una entrada de
api.anthropic.comen una lista de permitidos como una decisión de confianza sobre lo que pasa por ella.
Luego da a tus agentes una máquina donde la clave que tienen solo funcione camino de Anthropic, la red que pueden alcanzar sea la que tú enumeraste, y cada solicitud que hagan quede registrada donde no puedan cambiarla. Los sustitutos y el modo estricto se explican en el capítulo Credentials & the Wire Boundary del manual, la denegación por defecto y el centinela del kernel en Sandbox Policy, y la traza en Tracing & Audit.