GNU-linux-desktop-on-docker_logo

Docker for pentesters or switching GNU/Linux environment from virtual machines into containers

From ages ago till now there are plenty of discussions regarding the best/appropriate approach of using a pentesting OS: as a main, live system, dual boot as well as using it in virtual machine or in containers. First four approaches were discussed countless times and, definitely, each one has its strengths and drawbacks. But noticeable lack of information on using Docker as a main weapon for virtualization of your Kali Linux makes it tough to understand and use this approach. Today we will try to fill the gap, reveal main issues you may face and create an unified image for your further development.

 

0. Foreword

As per the best practices in writing articles we have to start from the explanation what Docker is, how it works and touch other related stuff. But from our point of view, it’s pointless because, 1. if you are reading it now you already know what Docker is; 2. if not, you can easily visit the official Docker web-site as well as developers’ articles; 3. the article would be extended for many-many pages.

So, let’s not waste the time and dig into the research. Before switching your Red Team environment into Docker containers, we have to be sure that all of the features are working properly and as intended. During the article we will be focusing on the next aspects:

  • Optimization
  • GUI (visualization)
  • Ports forwarding
  • Further customization
  • Transferring
  • Multiplayer

Let’s discuss them one by one.

  1. Optimization

Under the Optimization we mean Performance (improving the speed and responsiveness of an application or system), Resources (minimizing the amount of resources required to run an application or system) and Cost (minimizing the cost of running an application or system) optimization. Overall – a critical process that enables to maximize the value we get from our investments, while also ensuring that our systems and applications are performing at the highest levels possible.

To make it easier to understand, let us explain it in a simple example.

For instance, let’s assume you want to install Fast-Google-Dork-Scan application which you may find by the link: https://github.com/IvanGlinkin/Fast-Google-Dorks-Scan. Having downloaded the repository, we can see the next:

GNU-linux-desktop-on-docker_001

The whole repository is roughly 4 Mb. But we need only 1 file from it which is only 102 Kb weight or 2,5% out of rep. So, we can save 97,5% of the disk space.

You may say we are not in 60’s where we count each byte, but please don’t judge too early 🙂 We’ve only just started.

 

Now, let’s put our file into the container and make it work. The easiest approach (not the smartest one) is:

 

# Download the Kali repository

FROM kalilinux/kali-rolling:latest

 

# Download and install bash and curl (FGDS requires it) and git to download the App

RUN apt update && apt install -y bash git curl

 

# Download the App

RUN git clone https://github.com/IvanGlinkin/Fast-Google-Dorks-Scan.git

 

# Launch Fast-Google-Dorks-Scan

ENTRYPOINT [“bash”, “Fast-Google-Dorks-Scan/FGDS.sh”]

GNU-linux-desktop-on-docker_002
GNU-linux-desktop-on-docker_003
GNU-linux-desktop-on-docker_004

As we can see, it’s been successfully built and launched – everything is working perfect. But, before giving that approach 5-star, we have to check the image size:

GNU-linux-desktop-on-docker_005

I’m sorry, did I understand everything correctly? To launch a simple 102 Kb bash script I have to waste 302 Mb SSD space? Thank you, but no, thank you. We have to find another approach.

 

Let’s switch our view into another Linux distributive besides Kali. There is a great one called Alpine (https://www.alpinelinux.org/). The power of it is in its size. Instead of saying million words, we will show you the picture:

GNU-linux-desktop-on-docker_006

Wow, that is a significant size decrease. We can work with it further. But unfortunately, Alpine Linux doesn’t have bash, curl and git as well as in Kali by default hence we have to install them to make FGDS works. Let’s adjust our Dockerfile to use Alpine as a main OS:

 

FROM alpine:latest

 

RUN apk update && apk add –no-cache bash git curl

RUN git clone https://github.com/IvanGlinkin/Fast-Google-Dorks-Scan.git

 

ENTRYPOINT [“bash”, “Fast-Google-Dorks-Scan/FGDS.sh”]

 
GNU-linux-desktop-on-docker_007
GNU-linux-desktop-on-docker_008

Ok, it’s working, but let’s check the size:

GNU-linux-desktop-on-docker_009

Wow, that’s much better. Instead of 302 Mb now it’s 28,3 Mb – decreased by ~90%.

But… as we remember the ~4 Mb is the git repository from which we use only 102 Kb. Also, we are installing “git” application to make it possible to download git repositories. We think it’s a little bit “expensive” to use it only for the one small git. Let’s change the approach: we won’t install git app and download the whole repository, but instead download only the one bash executable file – FGDS.sh:

FROM alpine:latest

RUN apk update && apk add –no-cache bash curl

RUN curl https://raw.githubusercontent.com/IvanGlinkin/Fast-Google-Dorks-Scan/master/FGDS.sh -o ./FGDS.sh

ENTRYPOINT [“bash”, “./FGDS.sh”]

GNU-linux-desktop-on-docker_010
GNU-linux-desktop-on-docker_011

What about the size?

GNU-linux-desktop-on-docker_012

Now it’s perfect: twice lower than the previous one and 16,9 Mb instead of 302 Mb from the first iteration – ~95% size and time optimized. 

If you can decrease it more – we would love to hear your story, but from our point of view, it’s maximum that could be done.

 

 

2. GUI (visualization)

As you know the whole Linux power is in its command line. Definitely, for us like for other cybersecurity professionals across the globe it’s much easier to write 2-3 lines bash script rather than scroll-click-next-next-next-checkbox-… Also, using pipes you can connect different applications with each other without learning each app’s API models.

 

But, some of the applications work only over GUI (Graphical User Interface): Firefox + Foxyproxy, BurpSuite, Maltego, BloodHound, Wireshark, rdesktop/remmina, etc.

 

In that case GUI is required to be installed on you pentester’s laptop so you can perform web and mobile pentest, network analysis, OSINT, domain enumeration and other day-to-day hacker’s activity.

 

To achieve that, let’s compose our Dockerfile. Before doing this let’s agree we are using Kali Linux repository because: 1. We are creating a red teaming OS; 2. Kali has its own repository so we can download any kali application; 3. It’s a Debian based hence quite easy to manage (from our perspective 😉

 

First, let’s specify the base image that the Dockerfile will be built on top of. In our case, it’s the latest version of the Kali Linux rolling release.

 

FROM kalilinux/kali-rolling:latest

 

Next, we have to update the package repository information and install the XFCE desktop packages (XFCE is an open source Remote Desktop Protocol (RDP) server that will allow you to connect to a Linux desktop).

 

Setting DEBIAN_FRONTEND=noninteractive ensures that the apt package manager runs in a non-interactive mode and doesn’t prompt you for input, which is useful for building Docker images in an automated and unattended manner.

 

RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y kali-desktop-xfce xrdp

 

After that we have to create a new user and add him to the ssl-cert group.

 

RUN adduser xrdp ssl-cert

 

As you may know, RPD works only when the user has not only a login, but a password as well so let’s set it up.

 

RUN echo ‘root:toor’ | chpasswd

 

Next, we are adding environment variables to the ~/.xsessionrc file to configure our XFCE desktop environment when we connect via RDP.

 

RUN sed -i ‘3 a echo “\

export XDG_SESSION_TYPE=x11\\n\

export XDG_CURRENT_DESKTOP=XFCE\\n\

export XDG_CONFIG_DIRS=/etc/xdg/xfce4:/etc/xdg\\n\

” > ~/.xsessionrc’ /etc/xrdp/startwm.sh

 

Then open default RDP port – 3389

 

EXPOSE 3389

 

And finally, starting xrdp service.

p.s. as you may see we are stopping xrdp service first. That is done for the long-term work with the same container (not image, we will discuss that further in the article). So, once you decided to load the same container (not image) and connect via RPD that won’t work and stopping service first fixes that issue

 

CMD service xrdp stop ; service xrdp start ; bash;

 
GNU-linux-desktop-on-docker_013

Now, let’s launch that.

GNU-linux-desktop-on-docker_014

It took roughly 10 minutes to download all necessary libraries, install them and set up. The full image size is 2,51 Gb.

GNU-linux-desktop-on-docker_015

Now, it’s time to run the container and connect to it via RDP.

GNU-linux-desktop-on-docker_016

For RDP connection we are using “Microsoft Remote Desktop” which is totally free, but you are free to use whatever you like.

p.s. If you are connecting from the same machine where you are running Docker, you have to connect to the localhost, which has 127.0.0.1 as an IP-address. As a login and password use root:toor (if you didn’t change the default parameters).

GNU-linux-desktop-on-docker_017a

If you are connecting from another host within the same network, you have to put the Docker runner machine IP-address, which in our case is 10.93.176.130.

GNU-linux-desktop-on-docker_017

The whole solid Dockerfile to install Kali with GUI you may find below:

 

FROM kalilinux/kali-rolling:latest

 

RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y kali-desktop-xfce xrdp

 

RUN adduser xrdp ssl-cert

RUN echo ‘root:toor’ | chpasswd

 

RUN sed -i ‘3 a echo “\

export XDG_SESSION_TYPE=x11\\n\

export XDG_CURRENT_DESKTOP=XFCE\\n\

export XDG_CONFIG_DIRS=/etc/xdg/xfce4:/etc/xdg\\n\

” > ~/.xsessionrc’ /etc/xrdp/startwm.sh

 

EXPOSE 3389

 

CMD service xrdp stop ; service xrdp start ; bash;

 

3. Ports forwarding

Ok, what’s next? Of course, speaking of pentesting and red teaming can’t be full without reverse shell. Indeed, how can we receive a connection from the victim host to our Linux? I guess, that’s the easiest part.

 

To forward ports from the Docker host to a container, we can use the -p option when running the docker run command. The -p option maps a port from the Docker host to a port in the container.

 

In our case, the command that maps port 4444 and ports 8000-8010 from the Docker host to the same ports in a container is the next:

 

docker run -it –rm -p 3389:3389 -p 4444:4444 -p 8000-8010:8000-8010 kali-desktop

 

After running this command, any traffic that is sent to port 4444 or ports 8000-8100 on the Docker host will be forwarded to the same ports in the container. We can use these ports to communicate with services running inside the container.

 

Note that if the container is already running, we have to stop and then run the docker container with the new port mappings.

 

Let’s try it out. First, let’s run our container with mentioned keys.

GNU-linux-desktop-on-docker_018

After that let’s establish a connection.

Note, that netcat is not installed by default in Kali Linux, so we have to install that manually by the command:

 

apt-get install netcat-traditional

 
GNU-linux-desktop-on-docker_019

As we can see, port forwarding is working fine and we received the reverse shell from the victim machine hence let’s move forward.

 

 

4. Further customization

 

A. General terminal customization

As you already could have understood, Linux on Docker is an absolutely the same Linux like if you install it as a main, live or second system as well as on virtual machine. Just launch and start working.

 

But Docker Linux images include only limited number of necessary applications. So, if you need something particular you have to download and install that by yourself. It has both positive and negative aspects at the same time by decreasing the image size from the one hand and requiring to write down the instructions manually from another.

 

As a basis we will take the kali-desktop image discussed in the previous paragraphs. Consequently, we have already updated the source lists and installed XFCE working environment. So now let’s put some must-have hackers apps:

GNU-linux-desktop-on-docker_020

RUN apt install -y locate nmap dnsutils curl whois git nano nikto wfuzz sqlmap wireshark geoip-bin \

    metasploit-framework postgresql enum4linux wpscan crunch cewl python3-pip cutycapt ettercap-graphical \

    default-jre netcat-traditional rdesktop

RUN updatedb;

RUN service postgresql start; sudo msfdb init; msfconsole -q -x “msfdb reinit”

RUN echo “alias msfconsole=’service postgresql start; msfconsole'” >> /root/.bashrc

 

As you can mention, we are getting nmap, nikto, sqlmap and other day-to-day using tools. Nothing complicated, install any app in an exact way as it is on Linux.

But we would like to pop up onto your radar lines 19 and 20. If you are working with Metasploit app you know the last one requires PostgeSQL database. In the line 19 we start the DB service to perform initiating.

Also, based on the Docker specifics, the service won’t be running when we run the image hence, we have 2 possible ways:

  • Run service each time you launch the image (take some time before starting the image each time. But if you are not going to use msfconsole – waste of time and resources)
  • Run service once you launch the msfconsole (take some time before starting the app)

 

It’s all about optimization so we choose the 2nd way. Following that we created alias which starts the service before launching msfconsole by itself 🙂

 

BurpSuite for web testing is our next app:

GNU-linux-desktop-on-docker_021

RUN mkdir /root/tools/

 

# Install BurpSuite Community version 2023.3.5

RUN mkdir /root/tools/burp && \

curl ‘https://portswigger.net/burp/releases/download?product=community&version=2023.3.5&type=Jar’ -o /root/tools/burp/burp.jar

RUN echo “java -jar /root/tools/burp/burp.jar” > /root/tools/burp/burp && \

chmod +x /root/tools/burp/burp && ln -s /root/tools/burp/burp /usr/local/bin/burp

As a final stage, let’s install some custom apps from GitHub:

GNU-linux-desktop-on-docker_022

# Install Fast-Google-Dorks-Scan, AutoSUID, Domain_Checker, Holehe

RUN git clone https://github.com/IvanGlinkin/Fast-Google-Dorks-Scan.git /root/tools/Fast-Google-Dorks-Scan && \

    chmod +x /root/tools/Fast-Google-Dorks-Scan/FGDS.sh && ln -s /root/tools/Fast-Google-Dorks-Scan/FGDS.sh /usr/local/bin/FGDS

RUN git clone https://github.com/IvanGlinkin/AutoSUID.git /root/tools/AutoSUID && \

    chmod +x /root/tools/AutoSUID/AutoSUID.sh && ln -s /root/tools/AutoSUID/AutoSUID.sh /usr/local/bin/AutoSUID

RUN git clone https://github.com/IvanGlinkin/Domain_checker.git /root/tools/Domain_checker && \

    chmod +x /root/tools/Domain_checker/domain_checker.sh && ln -s /root/tools/Domain_checker/domain_checker.sh /usr/local/bin/domain_checker

RUN pip3 install holehe

 

We not just downloaded some custom tools, but also created a symbolic links for them.

 

So, an overall script is the next:

GNU-linux-desktop-on-docker_023

FROM kalilinux/kali-rolling:latest

RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y kali-desktop-xfce xrdp

 

RUN adduser xrdp ssl-cert

RUN echo ‘root:toor’ | chpasswd

 

RUN sed -i ‘3 a echo “\

export XDG_SESSION_TYPE=x11\\n\

export XDG_CURRENT_DESKTOP=XFCE\\n\

export XDG_CONFIG_DIRS=/etc/xdg/xfce4:/etc/xdg\\n\

” > ~/.xsessionrc’ /etc/xrdp/startwm.sh

 

EXPOSE 3389

 

RUN apt install -y locate nmap dnsutils curl whois git nano nikto wfuzz sqlmap wireshark geoip-bin \

    metasploit-framework postgresql enum4linux wpscan crunch cewl python3-pip cutycapt ettercap-graphical \

    default-jre netcat-traditional rdesktop

RUN updatedb;

RUN service postgresql start; sudo msfdb init; msfconsole -q -x “msfdb reinit”

RUN echo “alias msfconsole=’service postgresql start; msfconsole'” >> /root/.bashrc

 

RUN mkdir /root/tools/

 

# Install BurpSuite Community version 2023.3.5

RUN mkdir /root/tools/burp && \

    curl ‘https://portswigger.net/burp/releases/download?product=community&version=2023.3.5&type=Jar’ -o /root/tools/burp/burp.jar

RUN echo “java -jar /root/tools/burp/burp.jar” > /root/tools/burp/burp && \

    chmod +x /root/tools/burp/burp && ln -s /root/tools/burp/burp /usr/local/bin/burp

 

# Install Fast-Google-Dorks-Scan, AutoSUID, Domain_Checker, Holehe

RUN git clone https://github.com/IvanGlinkin/Fast-Google-Dorks-Scan.git /root/tools/Fast-Google-Dorks-Scan && \

    chmod +x /root/tools/Fast-Google-Dorks-Scan/FGDS.sh && ln -s /root/tools/Fast-Google-Dorks-Scan/FGDS.sh /usr/local/bin/FGDS

RUN git clone https://github.com/IvanGlinkin/AutoSUID.git /root/tools/AutoSUID && \

    chmod +x /root/tools/AutoSUID/AutoSUID.sh && ln -s /root/tools/AutoSUID/AutoSUID.sh /usr/local/bin/AutoSUID

RUN git clone https://github.com/IvanGlinkin/Domain_checker.git /root/tools/Domain_checker && \

    chmod +x /root/tools/Domain_checker/domain_checker.sh && ln -s /root/tools/Domain_checker/domain_checker.sh /usr/local/bin/domain_checker

RUN pip3 install holehe

 

CMD service xrdp stop ; service xrdp start ; bash;

 

Let’s create an image.

GNU-linux-desktop-on-docker_024

The whole process took ~27 minutes which is a little bit long. But we can see that the longest stage was downloading BurpSuite from the official web-site – 22 minutes.  

Overall, the image size is 5.66 Gb.

GNU-linux-desktop-on-docker_025

B. GUI customization

Right now we discussed about terminal installation and automatization.

But what if we have an application which can be installed and used only through GUI? Let’s take a simple example with FoxyProxy extension to Firefox browser. It’s quite annoying to install and set up the extension each time you launch a new container. So, let’s fix that issue as well.

 

First, let’s run the new container based on the kali-desktop image and log in through GUI.

!!! But, don’t use “–rm” key to the Docker command. It’s quite crucial due to rm key removes the container automatically after you exit the shell.

So, the command is the next:

 

docker run -it -p 3389:3389 kali-desktop

 

We will skip the FoxyProxy installation process because it’s not the aim of the article and just an example. Moreover, as a white/gray/black hat hacker you have to already know how to do that without my guide 😉

 
GNU-linux-desktop-on-docker_026

So, the question now is – can we save that status and have the FoxyProxy preinstalled each time we launch the new container?

Yes, we can so let’s do it.

Close the RDP and terminal. Then find out the container ID by the command:

 

docker ps -a

 
GNU-linux-desktop-on-docker_027

In our case the container ID is f2ccbce552aa. Using the next command we are creating the image based on it:

 

docker commit f2ccbce552aa kali-desktop-foxyproxy

 
GNU-linux-desktop-on-docker_028

Now let’s check if the image has been created.

GNU-linux-desktop-on-docker_029

Ok, so far everything is going as intended 🙂 The last step is to check the preinstalled apps.

GNU-linux-desktop-on-docker_030
GNU-linux-desktop-on-docker_031

Great. The customization went well.

 

5. Transferring

 

Another question could arise when you want to transfer your image preset to another PC (once you purchase a new one), your friend asked to share it with him, etc. Using Docker that couldn’t be easier. We just have to know only 2 minor Docker commands.

 

First, create an archive by:

 

docker save -o ./kali-image.tar kali-desktop-foxyproxy

 
GNU-linux-desktop-on-docker_032

Let’s check if our archive has been created.

GNU-linux-desktop-on-docker_033

Great. Now transfer the archive to a new PC and just launch:

 

docker load -i kali-image.tar

GNU-linux-desktop-on-docker_034

Excellent – our image mounted. But, because we are using the same machine, the image is overwritten.

Now, you can launch the container as you have already known.

 

6. Multiplayer

 

From our perspective, the last thing we have to discuss is all about different projects.

The issue pentesters and Red Teamers are facing is using the same Kali on multiple projects. Documents are mixing around, there is a big chance of being hacked back (which is not good for confidentiality), breaking something on Kali is affecting other projects and so on. So, the best practice is to split Kali’s images into dedicated ones for each particular project.

And as you may guess Docker is super good at it as well. Basically, you have to remember 2 commands as well as in previous section.

 

First, you have to run the container with 2 crucial aspects:

  • Don’t use the “–rm” key (to not delete the container);
  • Create the name for you project.

 

So, let us show you.

 

docker run -it –name project1 -p 3389:3389 kali-desktop

GNU-linux-desktop-on-docker_035

Let’s create a file into /tmp folder and save it for the further usage.

GNU-linux-desktop-on-docker_036

Now, let’s quit that session and create another container – project2.

GNU-linux-desktop-on-docker_037

As you can see, no files were there after the launch. So, we created the new one.

Now let’s quit that session as well and try to find our running containers:

 

docker ps -a

GNU-linux-desktop-on-docker_038

According to the output, we have 2 containers called project1 and project2.

So, how to reach them back. Easy, just run the next:

 

docker start -ai project1

 
GNU-linux-desktop-on-docker_039

Excellent, it’s all working as intended.

Now, you can create as many Kali containers as you want for your dedicated projects 🙂

 

p.s. As an alternative, instead of container name you can use container ID. But it’s not convenient when you have multiple ones hence you don’t know which container ID for what project. But, nevertheless, it’s all up to you.

 

docker start -ai b726ae3707c6

GNU-linux-desktop-on-docker_040

7. Useful commands

 

Build image from DockerFile

docker build -t NewImageName .

 

Run the image

docker run -it –rm -v /tmp:/tmp/ Image

-it – run a Docker container in interactive mode and allocate a pseudo-tty

–rm – removes the container automatically after you exit the shell

-v or –volume option to specify the directory you want to mount and the directory inside the container you want to mount it to

 

Show all images

docker images

 

Remove image

docker rmi Image

 

Force Remove image

docker rmi –force Image

 

Show all containers:

docker ps -a

 

Remove container

docker rm ContainerName

 

Use host network

–net=host – option, which enables the container to use the host’s network interface

 

Run nmap to scan network

docker run -it –rm –net=host nmap-image nmap 192.168.1.1

 

Reduce space on disc – use Alpine linux

FROM alpine:latest

RUN apk update && apk add –no-cache APPS

 

Load from previous container

docker ps -a

docker start -ai {ContainerID or ContainerName}

 

Generate an image from container

docker commit <container_id> <new_image_name>

 

Deliver a local Docker image to a new PC

docker save -o <path/to/save/image.tar> <image_name> #save the local image

docker load -i <path/to/image.tar> #execute on the new PC

 

 

8. Conclusion

Having considered all of the arguments above we may conclude that docker is the great stuff to perform penetration testing and red teaming activities as well. In some cases, it’s more convenient rather than use VM or dual boot. Just give it a try… 😉