Skip to main content

One post tagged with "cryptojacking"

View All Tags

Anatomy of an Unauthenticated Docker Engine API Takeover Chain

· 6 min read

Overview

Exposing an unauthenticated Docker Engine API port (TCP 2375) to the public internet is one of the quickest ways to lose control of cloud infrastructure.

My newly deployed Docker API honeypot captured automated botnet scanners executing a complete, sub-second 4-stage attack chain:

Within ~100 milliseconds of confirming API responsiveness, automated exploit scripts transition from basic banner grabbing to full interactive container takeover attempts.

1. Reconnaissance Scan

Uses zgrab/0.x to sweep public IPv4 ranges for open /v1.16/version endpoints.

Tool: Zgrab Framework

2. Health Verification

Spoofs Docker-Client/20.10.18 to confirm /_ping returns 200 OK.

Response Delta: ~100ms

3. Container Creation

Issues POST /containers/create JSON payload to instantiate an unprivileged container.

Payload: Go-http-client/1.1

4. Socket Hijacking

Issues Connection: Upgrade header to upgrade HTTP to a raw interactive TCP socket.

Impact: Interactive Shell Access

ATTACK CHAIN AT A GLANCE

Automated botnets sweep public IP ranges for exposed Docker Engine APIs, leveraging sub-second protocol upgrades to establish raw interactive shell access.

Sub-Second Delta110 ms from ping to socket upgrade
Primary ToolingZgrab / Go-http-client / Docker CLI Spoofing
Target VectorUnauthenticated Docker Sockets (Port 2375)

Methodology

To dissect this attack progression, my analysis separates the incident into distinct operational phases:

  1. Reconnaissance Identification: Filter raw TCP telemetry for initial port scans and banner probes (/version).
  2. Ping & Daemon Verification: Isolate requests validating API availability (/_ping).
  3. Payload Inspection: Analyze POST /containers/create JSON structures to extract container configurations and target images.
  4. Interactive Upgrade Extraction: Inspect POST /containers/attach requests for raw TCP socket upgrade headers (Upgrade: tcp).
  5. Timeline Correlation: Calculate exact millisecond deltas between API response and subsequent exploit execution.
  6. Indicator Generation: Aggregate attacker IPs, User-Agent strings, and target API endpoints into reusable IOC tables and detection logic.

Tools used

  • Honeypot container logging raw HTTP REST API traffic on port 2375
  • JSON telemetry parser for timestamp delta calculations and payload extraction
  • Mermaid sequence diagramming for protocol flow visualization

Investigation

Reconnaissance & API Version Probing

The attack chain begins with wide-scope internet scanning to discover exposed Docker daemons.

Attacker IPs (such as 140.238.153.39 and 101.206.108.14) issue a lightweight version check using the Zgrab scanner framework:

GET /v1.16/version HTTP/1.1
Host: <HONEYPOT_IP>:2375
User-Agent: Mozilla/5.0 zgrab/0.x
Accept: */*
Accept-Encoding: gzip

Using zgrab/0.x allows attackers to rapidly sweep public IPv4 ranges and flag hosts that return standard Docker version metadata.

Responsiveness Check

Once an IP is identified as open, a second request verifies that the Docker Engine API daemon is actively responding:

HEAD /_ping HTTP/1.1
Host: <HONEYPOT_IP>:2375
User-Agent: Docker-Client/20.10.18 (linux)
GET /_ping HTTP/1.1
Host: <HONEYPOT_IP>:2375
User-Agent: Docker-Client/1.13.1 (linux)
Accept-Encoding: gzip

By disguising their User-Agent as a legitimate Linux Docker CLI client (Docker-Client/20.10.18 or Docker-Client/1.13.1), the bot confirms that /_ping returns an HTTP 200 OK response.

Container Creation Attempt

Just 111 milliseconds after receiving the ping confirmation, the attacker's automated script issues an API request to instantiate a new container:

POST /v1.24/containers/create HTTP/1.1
Host: <HONEYPOT_IP>:2375
User-Agent: Go-http-client/1.1
Content-Length: 2214
Content-Type: application/json

{
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true
}

The payload specifies container parameters designed to run privileged tasks or mount underlying host filesystems (such as /host or /var/run/docker.sock).

Interactive Shell Upgrade

Immediately after submitting the container creation request (+110 ms), the bot attempts to attach an interactive socket stream to the container:

POST /v1.24/containers/attach?stderr=1&stdout=1&stream=1 HTTP/1.1
Host: <HONEYPOT_IP>:2375
User-Agent: Go-http-client/1.1
Content-Length: 0
Connection: Upgrade
Content-Type: text/plain
Upgrade: tcp
CRITICAL EXPLOIT VECTOR

Using the HTTP Connection: Upgrade header with Upgrade: tcp, the attacker requests the Docker daemon to switch the connection into a raw bidirectional TCP stream, providing direct interactive shell access to execute cryptojacking scripts (XMRig, kinsing) or host takeover commands.


IOCs

Indicator TypeValueDescription
Attacker IP140.238.153.39Active Docker API Takeover Scanner
Attacker IP101.206.108.14Active Docker API Takeover Scanner
Scanner User-AgentMozilla/5.0 zgrab/0.xZgrab Docker API Port Scanner
Client User-AgentDocker-Client/20.10.18 (linux)Automated Docker CLI Probe
Client User-AgentDocker-Client/1.13.1 (linux)Automated Docker CLI Probe
Target EndpointPOST /v1.24/containers/createContainer Creation Exploit Attempt
Target EndpointPOST /v1.24/containers/attachRaw TCP Shell Socket Upgrade Attempt

Detection Logic

IF
Destination Port = 2375 (Docker Engine API)
AND HTTP Request = GET /v1.16/version OR HEAD /_ping
AND User-Agent MATCHES "zgrab" OR "Docker-Client"
THEN
Docker API Reconnaissance Scan Detected
IF
HTTP Request = POST /v1.24/containers/create
AND Followed within < 2 seconds by POST /v1.24/containers/attach
AND Request Header contains "Connection: Upgrade" AND "Upgrade: tcp"
THEN
Automated Unauthenticated Docker Daemon Takeover Attempt Detected

Observations & Conclusions

  1. Sub-Second Execution Speed: Exploitation is entirely automated — the transition from /_ping to containers/create and containers/attach takes under 120 milliseconds.
  2. Standardized Toolchain: Attackers leverage zgrab for bulk port discovery, Go-http-client for REST API payloads, and spoofed Docker-Client headers for ping checks.
  3. Primary Intent: Unauthenticated Docker socket exposure remains a prime vector for automated cryptojacking campaigns (kinsing, kdevtmpf) aiming to deploy resource-intensive container workloads.
DEFENSIVE RECOMMENDATION

Docker TCP sockets should never be exposed unauthenticated on public interfaces (0.0.0.0:2375). Always enforce TLS mutual authentication (2376) or restrict access via SSH tunneling or firewall rules.

Indicators of Compromise (IOCs)
IOCs (domains, IP addresses, files, hashes, etc.) from this analysis are available on GitHub.
View on GitHub →