Running simple SSH honeypot with Docker
Setting up a honeypot is a very interesting technique to detect and diagnose system vulnerabilities, attack vectors and other things related to computer security. There are many different types of honeypots used in the wild, but the most simple ones are designed to run on systems with intentionally (or not) weakeaned security settings. With a few monitoring tools in place it gives you a good chance of catching bad guys, or most likely automated scripts, red handed.
In the world-wild-web the most common attack vector is targeted for SSH services. Pretty much every server that's not configured to run on private network will have either a standard or tweaked SSH port exposed to public. Accompanied with insecure (short, simple, default) passwords it makes the perfect target for all those bot nets and what not. And what could be possibly worse than a server with a bad root password?
What does it have to do with Docker? Well, one thing that Docker is good at is process and filesystem isolation, which ultimately gives us ability to run more stuff on the same box instead of having to deal with resource hogs like real VMs (VMWare, VBox). One day I was curios what would happen if I just leave a box with a dump root password exposed to internets. More specifically - how long will it take to get infected.
First thing, we'll need a Docker image that has vanilla Ubuntu 14.04 with OpenSSH server running on standard port 22. I made one for example:
FROM ubuntu:14.04
RUN apt-get update && \
apt-get upgrade -y \
apt-get install -y openssh-server && \
mkdir /var/run/sshd
RUN echo root:root | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
Then we just need to build the docker image:
$ docker build -t honeypot .
In order to make docker-based honeypot more effective, we'd need to change SSH
server setting on the host system so that honeypot could run on port 22. You can do
that by editing /etc/ssh/sshd_server
file and change the default port to something
like 2222. Make sure to restart SSH service with /etc/init.d/ssh restart
.
Now, lets get the party started:
$ docker run -d -p 22:22 honeypot
If you're using any cloud VPS like Digital Ocean there's a big chance that you
dont have to wait long. After running a few experiments I found that it takes
approximately 10-15 minutes before /var/log/auth.log
starts filling up with
failed ssh login attempts. Then some "miracle" happens and one of the bruteforcing
bots gets in and starts installing software, reconfiguring services, etc and ultimately
tries to restart SSH service which will end up with container dying.
It's time to scout. By default Docker uses AUFS filesystem driver and provides ability to see any filesystem changes between container's initial image and it's current state. Simply run diff command:
$ docker diff my-container-id
# C /etc
# C /etc/shadow
# C /etc/ssh
# D /etc/ssh/ssh_config
# A /lib/cpp
# C /root
Where A
- additions, D
- deletions and C
- changes.
This is pretty cool because now you dont even have to guess which files were changed
in the container. If your system got compromised you can track down every single
file that was changed in the process. When I first ran diff
command i got the
following:
$ docker diff b235c4bdf4be | wc -l
# 6169
Now, how do we get to see the actual file contents? First, if the container is still up and running, you can exec into it:
$ docker exec -it my-container-id bash
In case if container is no longer running, you can copy files from it to the host filesystem using docker cp command, or by jumping directly into container's filesystem diff directory. Obtain container's full ID by running inspect command and then change dir:
$ docker inspect my-container-id
$ cd cd /var/lib/docker/aufs/diff/6c85e7d768b6f405c8cb98b71d21f115ebe317614ae9daf98e822a6978f3301e
$ ls -al
# total 52
# drwxr-xr-x 13 root root 4096 Dec 19 18:10 .
# drwxr-xr-x 31 root root 4096 Dec 19 15:01 ..
# drwxr-xr-x 2 root root 4096 Dec 19 18:10 bin
# drwxr-xr-x 13 root root 4096 Dec 19 18:10 etc
# drwxr-xr-x 3 root root 4096 Dec 19 17:54 lib
# drwx------ 7 root root 4096 Dec 19 18:23 root
As an example, dig into compomised root's directory:
$ cd root
$ ls -al
total 4380
# drwxr-xr-x 2 root root 4096 Dec 19 13:28 .
# drwx------ 5 root root 4096 Dec 19 22:22 ..
# -rw-r--r-- 1 root root 2707 Dec 5 20:13 af
# -rw-r--r-- 1 root root 216 May 18 2005 auto
# -rw-r--r-- 1 root root 2205 Dec 19 12:14 get
# -rw-r--r-- 1 root root 2893 Oct 19 2011 mass
# -rw-r--r-- 1 root root 51845 Nov 13 07:33 passfile
# -rw-r--r-- 1 root root 171 Dec 19 07:02 port
# -rw-r--r-- 1 root root 888972 May 8 2015 pscan2
# -rw-r--r-- 1 root root 5843 Dec 14 05:15 pscan2.c
# -rw-r--r-- 1 root root 1246175 Dec 19 08:19 scan.log
# -rw-r--r-- 1 root root 453972 Oct 23 2010 ss
Pretty neat. Keep in mind that all above is a pretty simple (yet entertaining) setup to show you what happens when you don't protect your servers.
P.S. Some other interesting resources related to honeypotting: