Back to Intelligence

CARBONATO Docker Botnet: Detecting and Defending Against the AI-Powered Credential Theft Operation Targeting Exposed Docker Daemons

SA
Security Arsenal Team
September 26, 2026
12 min read

Security researchers at ThreatDown recently uncovered an operation that should be on every cloud and platform engineering team's radar. The operation — tracked as CARBONATO — is a Docker-based compromised device network active since at least October 2024. What makes CARBONATO notable isn't just its persistence in the wild; it's its business model. The botnet hunts for unauthenticated Docker daemons exposed to the internet, deploys an AI agent onto victim infrastructure, harvests API keys and credentials, and uses the stolen access to fund and operate its own LLM gateway service.

The discovery itself is a case study in attacker operational security failure: ThreatDown located an unauthenticated container registry exposed to the internet containing the attackers' entire toolchain — images, payloads, and orchestration logic laid bare. That registry gave defenders a rare, complete view of the operation's TTPs.

If you run Docker anywhere with a network path to the internet — development boxes, CI runners, cloud VMs, homelab-turned-production servers — you need to treat this as an active threat against your environment today, not a curiosity.

Technical Analysis: How CARBONATO Operates

Affected Platforms and Exposure Conditions

CARBONATO does not exploit a software vulnerability in the traditional sense. There is no CVE assigned to this campaign — and that's precisely the point defenders must internalize. The "vulnerability" is a misconfiguration: Docker daemons listening on TCP (typically ports 2375 for unencrypted HTTP or 2376 for TLS) without authentication or TLS client verification, reachable from the public internet.

Affected environments include:

  • Linux hosts with the Docker daemon socket exposed via tcp://0.0.0.0:2375 (commonly set in docker.service systemd unit overrides or daemon.json)
  • Cloud VMs and CI/CD build agents where Docker remote API access was enabled for convenience
  • Container hosts behind misconfigured security groups, firewalls, or load balancers that unintentionally expose the daemon port

An unauthenticated Docker daemon is functionally equivalent to unauthenticated root SSH access. Anyone who can reach the API can create a privileged container, bind-mount the host filesystem, and execute arbitrary commands on the host.

Attack Chain

From a defender's perspective, the CARBONATO kill chain unfolds as follows:

  1. Discovery / Reconnaissance: Internet-wide scanning for hosts responding on Docker API ports (2375/2376). The operators query the /version or /info endpoints to fingerprint live daemons.
  2. Initial Access: The attacker uses the Docker API to pull images from their own (now-discovered, unauthenticated) container registry and instantiate containers on the victim host — often with privileged: true, host PID/network namespaces, and the host root filesystem bind-mounted (/ mounted into the container).
  3. Payload Deployment: The deployed container installs an AI agent — an LLM-driven automation component that gives the operation its autonomous command-execution capability. This is the differentiator: rather than relying solely on static scripts, CARBONATO uses an AI agent to make decisions and execute commands on compromised hosts.
  4. Credential Harvesting: The malware hunts for API keys and credentials — cloud provider credentials (~/.aws/credentials, instance metadata service endpoints), environment variables containing secrets, SSH keys, and critically, LLM provider API keys (OpenAI, Anthropic, and similar). Because the container mounts the host filesystem and shares namespaces, every credential on the host is reachable.
  5. Monetization / Infrastructure Self-Funding: Stolen LLM API keys are used to power the operators' own LLM gateway — effectively reselling or consuming AI compute paid for by victims. Cloud credentials are similarly abused for infrastructure expansion.
  6. Propagation: The botnet spreads across networks autonomously, using the AI agent for command execution to identify and compromise additional reachable Docker hosts — meaning one exposed daemon can become a beachhead into adjacent internal infrastructure that was never internet-facing.

Exploitation Status

  • Active since at least October 2024 and ongoing.
  • Confirmed in-the-wild exploitation — this is not theoretical; ThreatDown recovered the full attacker toolchain from the exposed registry.
  • No CISA KEV entry (no CVE exists), but exposure scanning for Docker API ports is constant internet background noise; any newly exposed daemon is typically discovered by multiple actors within hours.

The strategic implication: CARBONATO represents the maturation of a trend we've been warning clients about — threat actors operationalizing LLMs inside malware for autonomous decision-making, and monetizing stolen AI compute as a revenue stream. Expect copycats.

Detection & Response

The detections below focus on the highest-fidelity, lowest-noise behaviors inherent to this attack pattern: Docker daemon API exposure, suspicious container creation via the API, container-to-host filesystem mounts, and credential file access from containerized processes.

Sigma Rules

YAML
---
title: Docker Daemon Listening on TCP Network Socket
tid: 3f8a1c92-7b4d-4e2a-9c15-8d6f2a1b3e47
status: experimental
description: Detects the Docker daemon being started with a TCP host binding, which exposes the Docker API over the network. Unauthenticated TCP exposure on ports 2375/2376 is the initial access vector used by the CARBONATO botnet.
references:
  - https://securityaffairs.com/199716/malware/ai-powered-carbonato-botnet-steals-credentials-to-fund-its-own-llm-gateway.html
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: process_creation
  product: linux
detection:
  selection_image:
    Image|endswith:
      - '/dockerd'
      - '/docker'
  selection_cli:
    CommandLine|contains:
      - '-H tcp://'
      - '--host tcp://'
      - '-H=tcp://'
      - 'tcp://0.0.0.0:2375'
      - 'tcp://0.0.0.0:2376'
  condition: selection_image and selection_cli
falsepositives:
  - Legitimate Docker remote API configurations in controlled internal networks (should still be TLS-secured and audited)
level: high
---
title: Docker Container Created With Host Root Filesystem Mount
id: 9c2e7f41-3a8b-4d96-b154-6f1a8c2d9e35
status: experimental
description: Detects docker run/create commands that bind-mount the host root filesystem or sensitive host directories into a container. CARBONATO deploys privileged containers with host mounts to harvest credentials and execute commands on the underlying host.
references:
  - https://securityaffairs.com/199716/malware/ai-powered-carbonato-botnet-steals-credentials-to-fund-its-own-llm-gateway.html
  - https://attack.mitre.org/techniques/T1611/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.privilege_escalation
  - attack.t1611
  - attack.t1610
logsource:
  category: process_creation
  product: linux
detection:
  selection_docker:
    CommandLine|contains:
      - 'docker run'
      - 'docker create'
  selection_dangerous:
    CommandLine|contains:
      - '-v /:/'
      - '--mount type=bind,source=/'
      - '--privileged'
      - '--pid=host'
      - '--net=host'
      - '-v /root'
      - '-v /home'
      - '-v /etc'
  condition: selection_docker and selection_dangerous
falsepositives:
  - Legitimate administrative container operations (backup agents, monitoring agents); tune per-environment with image allowlists
level: high
---
title: Credential File Access From Containerized Process
id: 5b1d9e83-2c4f-4a78-9613-7e4b5d2a8f16
status: experimental
description: Detects processes running under container runtimes accessing cloud provider credential files, SSH private keys, or AI/LLM API configuration files. CARBONATO harvests API keys and cloud credentials from compromised hosts to fund its own LLM gateway.
references:
  - https://securityaffairs.com/199716/malware/ai-powered-carbonato-botnet-steals-credentials-to-fund-its-own-llm-gateway.html
  - https://attack.mitre.org/techniques/T1552/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.credential_access
  - attack.t1552.001
  - attack.t1552.004
logsource:
  category: file_event
  product: linux
detection:
  selection_target:
    TargetFilename|contains:
      - '/.aws/credentials'
      - '/.aws/config'
      - '/.ssh/id_rsa'
      - '/.ssh/id_ed25519'
      - '/.azure/'
      - '/.config/gcloud/'
      - '/.kube/config'
      - '/.env'
      - 'openai'
      - 'anthropic'
  filter_runtime_legit:
    Image|endswith:
      - '/aws'
      - '/gcloud'
      - '/az'
      - '/kubectl'
      - '/ssh'
  condition: selection_target and not filter_runtime_legit
falsepositives:
  - Legitimate CLI tools reading their own credential stores (filtered); developers editing .env files
level: medium

KQL — Microsoft Sentinel / Defender

This query hunts Syslog-ingested Linux process events for Docker daemon TCP exposure and suspicious container creation matching the CARBONATO pattern. It assumes Syslog or AMA-ingested auditd/execve data flowing into Sentinel.

KQL — Microsoft Sentinel / Defender
// CARBONATO hunt: Docker API exposure and hostile container creation on Linux hosts
let lookback = 7d;
let DockerExposure = Syslog
| where TimeGenerated > ago(lookback)
| where ProcessName has_any ("dockerd", "docker")
| where ProcessCommandLine has_any ("-H tcp://", "--host tcp://", "tcp://0.0.0.0:2375", "tcp://0.0.0.0:2376")
| project TimeGenerated, Computer, HostIP, ProcessName, ProcessCommandLine
| extend Indicator = "Docker daemon TCP socket exposure";
let HostileContainer = Syslog
| where TimeGenerated > ago(lookback)
| where ProcessCommandLine has_any ("docker run", "docker create")
| where ProcessCommandLine has_any ("-v /:/", "--privileged", "--pid=host", "--net=host", "-v /root", "-v /etc")
| project TimeGenerated, Computer, HostIP, ProcessName, ProcessCommandLine
| extend Indicator = "Privileged container with host mount created";
union DockerExposure, HostileContainer
| sort by TimeGenerated desc
KQL — Microsoft Sentinel / Defender
// Companion hunt: outbound connections FROM dockerd to unexpected remote registries/IPs
// Pulling attacker images (as CARBONATO does from its own registry) is high-signal
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName has_any ("dockerd", "containerd", "docker")
| where RemotePort in (5000, 2375, 2376) // registry / daemon API ports
| extend RemoteIPType = iff(ipv4_is_private(RemoteIP), "private", "public")
| where RemoteIPType == "public"
| summarize Connections = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
  by DeviceName, InitiatingProcessFileName, RemoteIP, RemotePort
| sort by Connections desc

Velociraptor VQL

Deploy this as a hunt across your Linux fleet to identify exposed Docker sockets and recently created containers with host mounts — the two forensic fingerprints of CARBONATO compromise.

VQL — Velociraptor
-- CARBONATO Hunt: exposed Docker TCP sockets and suspicious container configuration
-- 1) Find dockerd processes listening on network sockets
SELECT Pid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ 'dockerd.*-H[ =]tcp://'
   OR CommandLine =~ 'dockerd.*tcp://0\\.0\\.0\\.0'
VQL — Velociraptor
-- 2) Enumerate Docker daemon configs for TCP host bindings
SELECT FullPath, Data.Hosts, Data.TLS, Data.TLSVerify, mtime
FROM glob(globs=['/etc/docker/daemon.json', '/etc/systemd/system/docker.service.d/*.conf', '/usr/lib/systemd/system/docker.service'])
LET parsed = SELECT FullPath, parse_json(data=read_file(filename=FullPath)) AS Data, mtime FROM glob(globs=['/etc/docker/daemon.json'])
SELECT FullPath, mtime, read_file(filename=FullPath) AS RawConfig
FROM glob(globs=['/etc/docker/daemon.json', '/etc/systemd/system/docker.service.d/*.conf'])
WHERE RawConfig =~ 'tcp://'
VQL — Velociraptor
-- 3) Review listening sockets owned by dockerd (port 2375/2376 exposure check)
SELECT Pid, Name, Status, Address, Port
FROM netstat()
WHERE Name =~ 'dockerd'
  AND Port in (2375, 2376)
  AND Address =~ '0.0.0.0|::'

Remediation & Hardening Script

Run this on Linux Docker hosts to audit for exposure, kill hostile containers, and lock down the daemon. Review before executing in production.

Bash / Shell
#!/usr/bin/env bash
# CARBONATO Response & Docker Daemon Hardening Script
# Run as root. Review output before applying destructive actions.
set -euo pipefail

echo "=== [1] Checking for TCP-exposed Docker daemon ==="
if ss -tlnp | grep -E ':(2375|2376)' | grep -q dockerd; then
  echo "[!] CRITICAL: dockerd is listening on a TCP socket:"
  ss -tlnp | grep -E ':(2375|2376)'
  echo "[!] If bound to 0.0.0.0, this host is/was exposed to CARBONATO-style compromise."
else
  echo "[OK] No TCP Docker daemon socket detected."
fi

echo "=== [2] Auditing daemon configuration for TCP hosts ==="
for f in /etc/docker/daemon.json /etc/systemd/system/docker.service.d/*.conf /usr/lib/systemd/system/docker.service; do
  [ -f "$f" ] && grep -Hn 'tcp://' "$f" && echo "[!] TCP binding found in $f"
done

echo "=== [3] Inventory: privileged containers and host mounts ==="
if command -v docker &>/dev/null; then
  for c in $(docker ps -aq 2>/dev/null); do
    PRIV=$(docker inspect --format '{{.HostConfig.Privileged}}' "$c" 2>/dev/null)
    MOUNTS=$(docker inspect --format '{{range .Mounts}}{{.Source}}->{{.Destination}} {{end}}' "$c" 2>/dev/null)
    IMAGE=$(docker inspect --format '{{.Config.Image}}' "$c" 2>/dev/null)
    if [ "$PRIV" = "true" ] || echo "$MOUNTS" | grep -qE '^/:|/->|/etc|/root|/home'; then
      echo "[!] Suspicious container $c (image: $IMAGE) privileged=$PRIV mounts: $MOUNTS"
    fi
  done

echo "=== [4] Images pulled from non-standard registries ==="
  docker images --format '{{.Repository}}:{{.Tag}}' | grep -vE '^(docker.io|library|mcr.microsoft|gcr.io|quay.io|registry.k8s.io|public.ecr.aws)' || echo "[OK] No unexpected registries."
fi

echo "=== [5] Hardening: enforce socket-only daemon access ==="
mkdir -p /etc/docker
if grep -q 'tcp://' /etc/docker/daemon.json 2>/dev/null; then
  cp /etc/docker/daemon.json /etc/docker/daemon.json.bak.$(date +%s)
  echo "[!] Backed up daemon.json. Manually remove the tcp:// hosts entry — do not run the daemon unauthenticated."
fi
# Remove any systemd override that adds -H tcp://
for f in /etc/systemd/system/docker.service.d/*.conf; do
  [ -f "$f" ] && grep -lq 'tcp://' "$f" && mv "$f" "$f.disabled.$(date +%s)" && echo "[+] Disabled override $f"
done
systemctl daemon-reload 2>/dev/null || true

echo "=== [6] Block daemon ports at host firewall (defense in depth) ==="
if command -v iptables &>/dev/null; then
  iptables -C INPUT -p tcp --dport 2375 -j DROP 2>/dev/null || iptables -A INPUT -p tcp --dport 2375 -j DROP
  iptables -C INPUT -p tcp --dport 2376 ! -s 10.0.0.0/8 -j DROP 2>/dev/null || iptables -A INPUT -p tcp --dport 2376 ! -s 10.0.0.0/8 -j DROP
  echo "[+] iptables rules added for 2375/2376."
fi

echo "=== [7] Credential exposure triage ==="
echo "[!] If exposure was confirmed: rotate ALL credentials on this host — cloud keys, SSH keys, LLM API keys, .env secrets. Assume full compromise."
ls -la /root/.aws/credentials /root/.ssh/ /home/*/.aws/credentials 2>/dev/null || true

echo "=== Done. Review all [!] findings. ==="

Remediation

There is no patch for CARBONATO because there is no product vulnerability — remediation is configuration, exposure management, and credential hygiene:

  1. Eliminate unauthenticated Docker API exposure immediately. Audit every host for Docker daemon TCP listeners (ss -tlnp | grep -E '2375|2376'). The daemon should bind to the Unix socket (/var/run/docker.sock) only. If remote API access is a hard requirement, enforce TLS with mutual client certificate verification per the official Docker documentation (https://docs.docker.com/engine/security/https/) — never plain TCP 2375, and never TLS without tlsverify.
  2. Cloud security groups and firewalls: Explicitly deny inbound 2375/2376 from the internet and from untrusted internal segments. Add these ports to your continuous external attack surface monitoring — CARBONATO's operators found victims through exactly this scanning.
  3. Credential rotation on any exposed host: If a host had an exposed daemon at any point, assume compromise. Rotate cloud IAM keys, SSH keys, Kubernetes service account tokens, secrets in .env files, and all LLM provider API keys (OpenAI, Anthropic, etc.). Review billing dashboards for anomalous LLM API consumption — CARBONATO monetizes through exactly this channel, and unexpected token usage is both an IoC and a financial bleeding point.
  4. Container governance: Enforce policy (OPA/Gatekeeper, Kyverno, or Docker Bench for CIS) blocking privileged containers, host PID/namespace sharing, and host root filesystem mounts. Restrict image pulls to approved registries via daemon configuration (--registry-mirror / admission control).
  5. Forensic review before cleanup: On confirmed-exposed hosts, preserve evidence — container image digests, docker events history, auditd logs, and registry pull records — before removing containers. CARBONATO's autonomous AI agent means command execution may have touched systems beyond the initial host; scope laterally.
  6. Network egress controls: Restrict outbound access from container hosts to known registries and required endpoints only. Blocking arbitrary outbound pulls would have prevented CARBONATO from retrieving its payloads from its own registry.

The Bigger Picture

CARBONATO is a preview of where crimeware is heading: autonomous, AI-augmented, and self-funding. The operators didn't need an exploit — they needed a misconfiguration that exists on thousands of internet-facing hosts at any given moment, plus an AI agent to scale decision-making across compromised infrastructure. The defensive lesson is unglamorous but decisive: attack surface hygiene on management interfaces, least-privilege container configuration, and rapid credential rotation discipline will defeat this entire class of operation. If you haven't audited your Docker exposure this quarter, do it this week — the scanners already have.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.