Il 22 settembre 2026, i ricercatori di ThreatDown hanno descritto il botnet CARBONATO. Accede ai server tramite un API Docker aperto senza password, avvia un agente IA sull'host e prima di tutto cerca le chiavi per i modelli linguistici. Le chiavi SSH e i token di accesso arrivano dopo. Se hai parser in esecuzione su VPS in contenitori, e nel .env ci sono chiavi OpenRouter o OpenAI e credenziali proxy, questo è il tuo profilo di rischio. Di seguito un'analisi di come è strutturato l'attacco e una checklist di 15 minuti che chiude questo accesso.
Cosa abbiamo trovato: 4,3 GB di immagini e un agente di nome GH0ST
Tutto è iniziato con un registro Docker non protetto degli stessi operatori. Secondo ThreatDown, conteneva 59 repository, 234 tag di immagini e 4,3 GB di dati. L'archivio copre il periodo da ottobre 2024 ad agosto 2026, il che significa che il botnet ha operato per quasi due anni prima di essere descritto. Nei repository sono stati trovati un miner XMRig e immagini con nomi del tipo fsociety/agent.
La catena di infezione secondo il rapporto appare così:
- Lo scanner cerca host dove l'API Docker è aperta su TCP 2375 senza autenticazione.
- Attraverso questa API, il worm avvia un contenitore privilegiato con il filesystem dell'host montato. Da questo momento è di fatto root sulla macchina.
- Viene stabilito un tunnel SSH inverso verso l'infrastruttura degli operatori, viene installato un server SSH con la loro chiave.
- Il mantenimento avviene tramite cron, timer systemd, rc.local e OpenRC, con i file contrassegnati come immutabili. I processi di sorveglianza riscaricano le immagini se qualcosa viene rimosso.
- Il contenitore si maschera da
systemd-resolved, mentre il processo si presenta come flusso del kernel[kworker/u2:0]. - Ogni cinque minuti, gli script scansionano le sottoreti vicine /24 e i bridge Docker in cerca del prossimo porto aperto 2375.
La diffusione è completamente automatica e non dipende dall'IA. L'IA qui è responsabile di ciò che accade all'interno del server già compromesso.
Perché il botnet ha bisogno di un agente IA e perché ha bisogno proprio delle chiavi LLM
Viene installato un framework aperto Hermes Agent con la persona GH0ST (le sue istruzioni si trovano nel file SOUL.md). L'operatore scrive un compito su Telegram, l'agente lo inoltra insieme alle istruzioni al gateway LLM dell'operazione. Il modello analizza il compito, scrive comandi per il terminale, legge l'output e decide cosa fare dopo. I risultati tornano su Telegram.
Nelle istruzioni dell'agente, le priorità sono chiaramente indicate. ThreatDown cita: «Le chiavi API AI sono la priorità assoluta. Esfiltrate prima». Nella lista ci sono 14 fornitori di modelli, tra cui OpenAI, Anthropic, Google, Groq, Mistral e OpenRouter. Gli account SSH, i token di accesso e i dati delle basi seguono come punti successivi.
La logica è semplice: una chiave LLM rubata si trasforma immediatamente in calcoli gratuiti o in merce da rivendere, e a pagarli è il proprietario della chiave. A differenza del mining, tale furto non è visibile dal carico sulla CPU. Lo si nota solo dalla fattura del fornitore del modello.
Perché questo riguarda chi fa scraping
Il tipico stack di scraping nel 2026 appare così: VPS, diversi contenitori (crawler, coda, database, browser headless), LLM per l'analisi delle pagine e un pool di proxy. Tutti i segreti si trovano in un unico .env o nelle variabili d'ambiente dei contenitori. Per un agente che «legge tutto» con accesso root, questo è un bottino pronto in un solo file:
- chiavi LLM: è per questo che è stato creato CARBONATO;
- credenziali e password proxy: il rapporto non le evidenzia separatamente, ma l'agente con accesso root raccoglie qualsiasi account e token che vede, e le credenziali proxy di solito si trovano nelle vicinanze;
- chiavi cloud e accessi ai database con i risultati dello scraping;
- il server stesso: XMRig nello stesso archivio significa che la CPU del tuo crawler andrà al mining, e i compiti inizieranno a fallire per timeout.
Un problema separato riguarda la reputazione. Il server da cui il worm scansiona le sottoreti altrui finisce rapidamente nelle liste di abuso, e l'hosting provider può bloccarlo su segnalazione. Per lo scraping, questo è un colpo doppio: l'IP del server è contrassegnato, e le credenziali proxy rubate stanno già consumando il tuo traffico con richieste altrui.
Come la porta 2375 può risultare aperta, anche se non l'hai aperta
Per impostazione predefinita, Docker ascolta su un socket UNIX locale, non sulla rete. La porta 2375 appare quando qualcuno ha volontariamente aggiunto -H tcp://0.0.0.0:2375 nella configurazione del demone. Di solito, questo viene fatto per connettere un IDE remoto, CI o un pannello di controllo dei contenitori, e poi se ne dimentica. La documentazione di Docker avverte esplicitamente che l'accesso al demone equivale all'accesso root alla macchina, e consiglia di proteggere le chiavi come una password root. La versione crittografata con TLS funziona sulla porta 2376, mentre 2375 significa testo aperto senza verifica del client.
La seconda trappola colpisce coloro che sono certi di avere «ufw attivo». Nella documentazione di Docker si afferma che il traffico delle porte pubblicate dei contenitori viene reindirizzato nella tabella nat prima delle catene INPUT e OUTPUT, su cui si basa ufw. Nella pratica, le regole di ufw per tali porte semplicemente non si attivano. Se hai avviato Redis, un pannello di coda o un gestore proxy con -p 6379:6379, la porta è esposta a Internet, qualunque cosa mostri ufw status.
Checklist di 15 minuti per un server con parser
1. Controlla che l'API Docker non ascolti sulla rete
- Controlla le porte in ascolto:
ss -tlnp | grep -E '2375|2376|dockerd'. Se nell'output appare0.0.0.0:2375o:::2375, chiudi immediatamente. - Controlla da dove proviene il flag:
/etc/docker/daemon.json(chiave"hosts") e unitsystemctl cat docker(rigaExecStartcon-H tcp://). - Rimuovi l'ascoltatore TCP e riavvia il demone. Per la gestione remota, utilizza il contesto SSH:
docker context create remote --docker host=ssh://user@server. La porta esterna non è necessaria affatto. - Se il TCP è comunque necessario (CI, orchestratore), allora solo 2376 con autenticazione mutua TLS e lista bianca degli IP sorgente.
2. Controlla cosa è esposto all'esterno dai contenitori
- Esegui
docker ps --format '{{.Names}} {{.Ports}}'. Tutto ciò che inizia con0.0.0.0:è accessibile da Internet bypassando ufw. - I servizi di utilità (Redis, Postgres, Mongo, pannelli di coda, Selenium Grid, API del gestore proxy) pubblicali solo su indirizzo locale:
-p 127.0.0.1:6379:6379. L'accesso esterno fallo tramite tunnel SSH. - Se non puoi fare a meno di una porta esterna, filtra nella catena
DOCKER-USER: Docker non la sovrascrive, ed è proprio questa che si applica al traffico dei contenitori. - Non mantenere un proxy aperto sul server senza autorizzazione (Squid su 3128, SOCKS su 1080 «per i propri»). Gli scanner trovano regolarmente tali porte, e attraverso il tuo IP passa traffico altrui con lamentele altrui.
3. Gestisci i segreti
- Separa le chiavi: una chiave LLM separata per ogni server o progetto, con limiti di spesa dal fornitore del modello. Una chiave rubata con un limite di $20 è un problema, senza limite è un buco nel budget.
- Distribuisci anche le chiavi proxy per compiti: un login separato (sub-account) per ogni parser. In questo modo, una fuga è visibile dal consumo di un login specifico, e puoi revocarlo senza fermare il resto del lavoro.
- Non passare tutto il
.envnel contenitore tramiteenv_file, se il servizio ha bisogno solo di due chiavi su venti. - Dove possibile, lega l'accesso all'IP del server: lista bianca presso il fornitore di proxy o limitazione della chiave API per indirizzo.
Per ulteriori dettagli su dove e come conservare le credenziali proxy negli script e nei contenitori, abbiamo scritto un'analisi su la conservazione sicura delle credenziali proxy.
4. Rimuovi privilegi superflui
- Non avviare contenitori con
--privilegede non montare/o/var/run/docker.sockall'interno senza necessità estrema. Il socket all'interno del contenitore è come avere root sull'host. - Per i browser headless, di solito bastano
--shm-sizee un profilo seccomp. La modalità privilegiata «per far partire Chrome» è un cattivo compromesso.
Come capire se sei già stato compromesso
ThreatDown e le analisi del suo rapporto indicano i seguenti segni di compromissione:
- file
SOUL.mdcon la parola GH0ST (ad esempio,/root/.hermes/SOUL.md); - variabile d'ambiente o stringa in
.env:CARBONATO_API_KEY; - file
/usr/local/bin/.docker-network-monitore sospetto/usr/sbin/systemd-logind; - contenitore con nome
systemd-resolved(il vero systemd-resolved è un servizio dell'host, non un contenitore); - traffico in uscita imprevisto verso l'API di Telegram e tunnel SSH inversi verso AS262145;
- connessioni agli indirizzi 45.79.183.61, 213.136.79.115, 190.211.124.187;
- file immutabili in cron e systemd:
lsattr /etc/cron.d/* /etc/systemd/system/*mostrerà il flagi.
Se anche solo un segno corrisponde, pulire il server manualmente è inutile: il mantenimento è multilivello, e il guardiano ripristinerà gli impianti. L'ordine corretto è il seguente:
- Da un'altra macchina, revoca tutte le chiavi che erano sul server: LLM, cloud, database, proxy.
- Controlla il consumo di ogni chiave nelle ultime settimane presso i fornitori. Le statistiche sul login proxy mostreranno immediatamente il traffico altrui.
- Avvia un nuovo server da un'immagine pulita, emetti nuove chiavi e solo dopo trasferisci i dati, senza binari e file cron dalla vecchia macchina.
Dove sono i proxy e cosa non risolvono
I proxy non proteggono il server da CARBONATO. Il worm non arriva tramite le tue richieste in uscita, ma attraverso la porta in ingresso. Tuttavia, uno schema di lavoro corretto con i proxy riduce i danni. Login separati per compiti, limiti di traffico e legami per IP trasformano una fuga da «tutto il saldo è andato» a «ho revocato un login».
C'è anche un lato opposto, che i botnet mostrano regolarmente: i dispositivi catturati altrui diventano «proxy residenziali» di reti discutibili. Pertanto, per lo scraping è consigliabile ottenere traffico da un fornitore con una provenienza chiara del pool. Per la maggior parte dei compiti di raccolta dati, andranno bene proxy residenziali con pagamento per gigabyte, dove il consumo per ogni proxy è visibile nel pannello. Per compiti di servizio senza una rigorosa protezione anti-bot, bastano proxy di data center più economici.
Conclusione
CARBONATO non utilizza né vulnerabilità zero-day né exploit sofisticati. Entra dalla porta che i proprietari dei server hanno aperto da soli: TCP 2375 senza password. La novità sta nel fatto che all'interno opera un agente IA, incaricato di recuperare per primo le chiavi per i modelli. Per coloro che raccolgono dati sui propri VPS, la conclusione è pratica. Chiudi l'API Docker, pubblica le porte di servizio su 127.0.0.1, distribuisci le chiavi LLM e proxy per compiti con limiti di spesa. Sono 15 minuti di lavoro, e dopo di ciò il tuo server diventa un obiettivo poco interessante per tali botnet.
