We often have a need to run a Kali image in an EC2 environment and Offensive Security no longer maintains a Kali AMI. While it is possible to create a Kali image from a Debian image, it is not recommended nor is it supported. The officially supported method for running a current Kali box in EC2 is to use the Kali Docker image on the OS of your choice. I am a fan of Debian-based systems so I chose to build our Kali system on Ubuntu. Below are the steps we use to build the Kali system, along with a link to a script to make it easier, and the basic usage instructions. Since Kali is running in a container, using it is a bit different than you may be used to.
Building Docker
- Build a new Ubuntu 14.04 instance that has t2.medium specs or higher.
- Configure the root drive to be 40GB.
- Configure the Security Group and SSH key to match your normal settings.
- Access the new instance via SSH and copy this script to it.
- Run the script and when it is finished you will have a Kali Top 10 Docker image.
Running Docker
Once the Docker setup is complete, you can access the Kali server by running:
sudo docker run --net=host -it kali:v1 /bin/bash.
This will give you a root shell in Kali just like you typically have. If you are doing any work that does not need to be saved on the Kali image, such as running fierce, theHarvester, dirb, etc, then you can exit the Docker image when you are finished and there is nothing else to do. Each time you need Kali, just run the above command.
However, if you are running a tool like Metasploit and loading Nmap scans into the database, you will want those changes to persist the next time you run the Kali image. To do that you will need to create an updated Kali image using the commands below. The next time you need Kali, you will run the same command as above but you will use the new image name you create.
Saving an Image
If you need your data to persist, then immediately after exiting Docker, run the following command where N is simply the next highest number. This will create a new Docker image with the name kali:vN. This will take a bit of time and will produce a SHA256 hash of the new image when it is finished.
sudo docker commit $(sudo docker ps -lq) kali:vN
To run this saved image, use the following command where N is the same number you used above, which will be the last version you created.
sudo docker run --net=host -it kali:vN /bin/bash
Deleting an Image
Keep in mind that the base system you installed has a 40GB hard drive and each Kali image you save will take up at least 4GBs so you may have to delete some older images. To do that, use the following commands:
sudo docker images -a
The output will look something like this:
You can then delete an image using the following command:
sudo docker rmi <image_id>
Mounting A Host Volume
Docker provides a way to copy files from a container (the latest run of an image) to the host using the cp command, which you can read about here: https://docs.docker.com/engine/reference/commandline/cp/.
The easiest thing to do is to mount a host volume into the container and save all of your data there. To do this:
- Create a new directory in the /home/ubuntu folder on the host:
- mkdir /home/ubuntu/client
- Run the Docker container as above but use the -v command to mount the volume:
sudo docker run -v /home/ubuntu/client:/root/client --net=host -it kali:vN /bin/bash.
Using a mounted volume may prevent the need for saving images as often. For example, if you run an Nmap scan and save the data to the client folder, then there is no need to save the image of the container because you have the data saved on the host. If you are loading the data into Metasploit in the Docker container, then it would be necessary to save the image each time you exit to ensure the Metasploit database is persisted.
Quick Note on Metasploit
If you start the Docker image with --net=host, the su command will not work properly, which means the msfdb init command will not work properly. Start the Docker image without --net=host, run msfdb init, then save the image. After that you can launch Docker with --net=host, start the postgresql server, then launch msfconsole.