Containerizing Your C2: Nuages, Docker, & A Dusty Pi

Why?

I wanted a low powered container platform and had a rPi 3b sitting around collecting dust. This project isn't for any practical reasons, but I wanted to emulate what bigger companies do, dynamically create C2's as they need for any client operations. I also figured this would be a good learning experience for Docker.

What software was used?

Platform:

Docker:

Server:
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.8
  Git commit:       afacb8b7f0
  Built:            Wed Mar 11 22:48:33 2020
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.3.3-0ubuntu2 

Ubuntu:

Static hostname: ubuntu
         Icon name: computer
        Machine ID: 577559a1018f47d3828d7448607a6aa1
           Boot ID: b35d8bf81ae246dd9ee52d653b9e11e4
  Operating System: Ubuntu 20.04 LTS
            Kernel: Linux 5.4.0-1008-raspi
      Architecture: arm64 

Containers:

Mongodb:latest
Debian Buster

How did this come together?

Nuages Dockerfile:

FROM debian:latest

COPY Nuages /

WORKDIR /Server/

RUN apt-get update -qy;\
        apt-get install python3 -qy;\
        apt-get install npm -qy;\
        npm install;\
        chmod +x setup.js;\
        node setup.js matt matt mongodb://192.168.10.66:27017;\
        npm install

WORKDIR /Clients/Nuages_Cli/

RUN npm install

WORKDIR /Server/

CMD ["bash", "start.sh"]


I rewrote a fair amount of the setup.js file from P3nt4s' original Nuages so that it could take parameters being passed from the CLI. It runs through our needed setup that'd be taken care of by the setup.sh script normally. I'm passing the username: matt password: matt and the database string that we will be setting up next. It also sets up the NPM dependencies for us. Find the updated copy of setup.js on my Github. Another area to note, I don't define the user running this container, meaning it's running as root. This can be a problem if the container were to be compromised and something we will fix.

Build this with:
docker build -t nuages_template .

I then used Docker to run the Mongodb instance
docker run --rm -d -p 27017:27017 mongo 

This downloaded and setup a MongoDB container with port 27017 mapped from the host to it. This also meant that UFW had to know to allow 27017 in. We also have to allow the beacon port in for Nuages, so might as well knock both out in the same go. I didn't hard code the port into the Nuages script as I wanted to be able to change that easily. We'll use port 8080 for now:
sudo ufw allow 27017
sudo ufw allow 8080
sudo ufw reload  

Now that everything on UFW and Mongo is ready to go, let's run our Nuages container:
docker run --rm -d -p 8080:8080 nuages_template  

This should return successfully and have port 8080 mapped from it to the host. You can terminal into it with docker exec -it <containerID> /bin/bash and get access to the C2 features.

Constraints & Lessons learned?

64bit architecture versus 32bit. The first images I used for testing this were all 32bit. I didn't think anything of it at the time, but when trying to get my Nuages container to work with my MongoDB instance, the version of Mongo was incorrect and there wasn't another available. I then tried searching for a Docker container that could run Mongo and nothing was showing up. In my first test before moving to my rPi, I was running Debian Buster 64bit and figured that Raspbian is based on Debian so this should carry over fine. I was wrong. The 32bit nature of Raspbian posed a big challenge that I wasn't able to get around, so I swapped to Ubuntu 20.04 ARM64 image.