In the last months I have been working intensively with honeypots. Honeypots are real or simulated systems used to analyze and detect attacks in a network. By posing as a vulnerable system, they attract curious attackers. Any connection to such a device can be considered suspicious, as they are only used for the given purpose and can usually only be found by scanning and probing a network.
To give you an idea how they work, I present you Cowrie, a “medium interaction” honeypot that simulates an SSH server. Medium-interaction refers to the interaction between an attacker and the system. There are low-interaction honeypots that only simulate specific services (SSH, FTP, Web server) and there are high-interaction systems that run complete operating systems with the real services (sshd, a database server, etc). Cowrie only simulates SSH and Telnet, but it also provides a fake filesystem and a fake Linux shell if the attacker manages to “compromise” the system.
Cowrie is written in Python and since the user cannot escape the simulated environment, the actual system it runs on is untouched. The point of honeypots is to log the attacker’s actions, and Cowrie is not different. It generates logs of the provided username/password combinations and allows to define which combination is allowed to enter the fake shell environment. The commands entered by the attacker are not executed on the system, common Linux commands like
cat are just simulated.
Also, the simulated filesystem can be made to look like any Linux distribution.
Run with Docker
I am a big fan of Docker, so I will use it to run Cowrie. You can follow along if you use Docker or you can install and run it on your local system by following the Installation guide on GitHub. I expect you to know how to use a SSH client, since we will be connecting to the Cowrie SSH service.
Pull the image:
docker pull cowrie/cowrie
Using default tag: latest latest: Pulling from cowrie/cowrie d2ca7eff5948: Pull complete 664fdb697b21: Pull complete abc94a586b7b: Pull complete 7a46c587cbe6: Pull complete c38563c3e1c2: Pull complete Digest: sha256:22a2c2376995107064371d2ad1e26bd3c7a5005649827c80e30022a4bd4df4a6 Status: Downloaded newer image for cowrie/cowrie:latest
Then run the container with:
docker run -d --name cowrie -p 2222:2222 cowrie/cowrie
This starts the service on port 2222 of the docker container. You can connect to it by finding out the container’s IP:
docker inspect cowrie | grep IPAddress
"SecondaryIPAddresses": null, "IPAddress": "172.17.0.2", "IPAddress": "172.17.0.2",
If you are on Windows, remove the part after the docker command and look for IPAddress in the output.
Then use the above IP address to connect to Cowrie. On most Linux distributions, you can use the
ssh command, with Windows use PuTTY or any modern alternative to it. Use the Port 2222 as it was the port we exposed through Docker. You can specify any username, but the default Cowrie config only accepts “root” or “richard” with any password.
ssh firstname.lastname@example.org -p 2222
The authenticity of host '[172.17.0.2]:2222 ([172.17.0.2]:2222)' can't be established. RSA key fingerprint is SHA256:8fPlZMfPE+M0nrlD3c93PDKXCmwkywU/3S4XQfZv/JU. Are you sure you want to continue connecting (yes/no)? yes Password:
The password prompt is from Cowrie, and if you used
root@ as the user, you can enter any password to enter the simulated system. You get the following prompt:
The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. root@svr04:~#
Now you can use the fake shell to look through the system. You can look through the file system, which looks like a real Debian system:
root@svr04:~# w 22:21:52 up 15 min, 1 user, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 172.17.0.1 22:21 0.00s 0.00s 0.00s w root@svr04:~# pwd /root root@svr04:~# ls -al / drwxr-xr-x 1 root root 4096 2013-04-05 12:03 . drwxr-xr-x 1 root root 4096 2013-04-05 12:03 .. drwxr-xr-x 1 root root 4096 2013-04-05 11:53 bin drwxr-xr-x 1 root root 4096 2013-04-05 12:02 boot drwxr-xr-x 1 root root 3060 2013-04-05 12:03 dev drwxr-xr-x 1 root root 4096 2013-04-05 12:06 etc drwxr-xr-x 1 root root 4096 2013-04-05 12:02 home lrwxrwxrwx 1 root root 32 2013-04-05 11:53 initrd.img -> /boot/initrd.img-3.2.0-4-686-pae drwxr-xr-x 1 root root 4096 2013-04-05 12:01 lib drwx------ 1 root root 16384 2013-04-05 11:52 lost+found drwxr-xr-x 1 root root 4096 2013-04-05 11:52 media drwxr-xr-x 1 root root 4096 2013-04-05 11:52 mnt drwxr-xr-x 1 root root 4096 2013-04-05 11:52 opt dr-xr-xr-x 1 root root 0 2013-04-05 12:03 proc drwx------ 1 root root 4096 2013-04-05 12:25 root drwxr-xr-x 1 root root 380 2013-04-05 12:06 run drwxr-xr-x 1 root root 4096 2013-04-05 12:03 sbin drwxr-xr-x 1 root root 4096 2013-04-05 11:52 selinux drwxr-xr-x 1 root root 4096 2013-04-05 11:52 srv drwxr-xr-x 1 root root 0 2013-04-05 12:03 sys drwxrwxrwt 1 root root 4096 2013-04-05 12:17 tmp drwxr-xr-x 1 root root 4096 2013-04-05 11:52 usr drwxr-xr-x 1 root root 4096 2013-04-05 11:52 var lrwxrwxrwx 1 root root 28 2013-04-05 11:53 vmlinuz -> /boot/vmlinuz-3.2.0-4-686-pae
This looks impressing at first, but you get to the limits of the fake filesystem pretty fast:
root@svr04:~# cat /var/log/syslog None root@svr04:~#
As you can see, you can simulate files, directories and file contents, but you need to specify it beforehand by configuring Cowrie. In its default configuration, there is not much to do. Next, let’s look at the logs.
Inspect the logs
You can inspect the logs with the following command:
docker exec cowrie /bin/sh -c "cat log/cowrie.log" | less -r
Example output (shortened)
New connection: 172.17.0.1:54000 (172.17.0.2:2222) [session: 7bb2e6981c46] [...] login attempt [root/anypassword] succeeded [...] CMD: w Command found: w CMD: pwd Command found: pwd CMD: ls -al / Command found: ls -al / [...]
You can look at source IP addresses, login credentials etc. All of this is valuable data if you are interested in how SSH services are breached.
When you are finished, remove the service again with
docker stop cowrie && docker rm cowrie.
Since you are inside a Python process, you are pretty much isolated from the real system. Add a Docker container as another layer and proper port forwarding and you have your very first (pretty safe) honeypot system online.
Cowrie is a really cool software and if you have any machine that is reachable from the outside which runs it, you get to see how a huge number of connection attempts reaches your machine, with most attackers brute-forcing login credentials until any goes through. Then you can take the logs (which are also generated in JSON format) and use it for improving your firewall rules. Or you can create cool statistics about the most used user/password combinations (Spoiler: the most used password is