← Volver a todas las publicaciones
Publicado el · por Renaud Deraison

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:

  1. Buscar en la red local SSH, SMB y FTP. El agente usó ip, ss y nc y encontró un servidor en 192.168.1.2.
  2. Ejecutar un comando nmap concreto contra ese servidor.
  3. Descargar lo que ofrece el recurso FTP anónimo. Contenía datos de empleados y una contraseña sin nombre asociado.
  4. Armar una lista de usuarios con los nombres de los empleados: 190 entradas en /tmp/usernames.txt.
  5. Probar la contraseña contra todas las cuentas en el controlador de dominio por SMB. Funcionó con una.
  6. Listar con smbclient los recursos SMB que ve esa cuenta.
  7. Listar el contenido de un recurso, que incluía un archivo de 1 GB.
  8. Descargar ese archivo a una carpeta temporal.
  9. 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.

Living off the AI (laboratorio Darktrace, 12 de noviembre)1. Robar la clavecurl … | dashencuentra Claude Code,toma credencialesde API y OAuthcurl → servidor del atacante2. Memory storeen el espacio de Consoledel desarrolladorheartbeatinput (trabajos)output (resultados)3. El agente implantesystemd-runrelanza Claude Code:lee el trabajo, lo ejecutacon bash, anota el resultadola carga se borra4. Los trabajosnc, nmap 192.168.1.2FTP anónimospray SMBrecursos smbclient1 GB → Files APICada paquete desde el paso 2api.anthropic.com /v1/filesEl host que tu firewall ya permite a los agentes. Ningún servidor que bloquear.
La cadena del laboratorio de Darktrace. Una vez que las credenciales robadas salen de la máquina, cada orden, resultado y subida viaja a api.anthropic.com, un host que la mayoría de las redes permite para los agentes de código.

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.

VM de la máquinaLo que encuentra la cargask-ant-api03-brm-…suscripción: ningún token en la VMLos trabajosnc, nmap, smbclient→ 192.168.1.2Enforce binariescada conexión ligada a su programa;sin sudo, sin DockerTu MacTrampassustituto al servidor del atacante:HTTP 451, VM en pausaclave del atacante: modo estrictoDenegación por defecto192.168.1.2 rechazadoal agente: no reintentarAgent watchdográfaga de bloqueos, gran subida:red cortada, VM en pausaVerlo, deshacerloTrace Inspectormétodo, ruta, bytes por solicitudcuerpos de Anthropic analizados:cada trabajo, cada llamadaNetwork lineageclaude → bash → nmap→ 192.168.1.2 rechazadoWipe and Launcho Rewind home / Reset disk;tokens y ajustes intactos
La misma cadena en una máquina Bromure. La clave robada es un sustituto y pausa la VM camino del servidor de preparación. Una clave que trae el atacante no supera el modo estricto. Los escaneos chocan con la denegación por defecto en el Mac, el watchdog corta la red ante una ráfaga de bloqueos o una subida desmesurada, y la traza guarda cada trabajo en texto claro.

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, smbclient o herramientas parecidas, sobre unidades systemd-run que 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.com en 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.