Summary
I setup a honeypot using Cowrie, a fork of the retired project known as Kippo (last updated 2014), which itself was inspired from Kojoney (last updated 2006).
These are my instructions for setting up the honeypot.
Initial setup
Start with a VirtualBox VM running 64-bit Ubuntu 16.10. Follow the steps as described in Setting Up A Ubuntu Development VM (2016-10 Edition).
Determine which TCP ports are open. There should be very little:
sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 948/systemd-resolve
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN 1041/dnsmasq
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 948/systemd-resolve
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 947/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 8264/cupsd
tcp6 0 0 :::5355 :::* LISTEN 948/systemd-resolve
tcp6 0 0 :::22 :::* LISTEN 947/sshd
tcp6 0 0 ::1:631 :::* LISTEN 8264/cupsd
Cowrie will be setup to run on TCP port 22 (SSH), so shut down the real SSHD. While I'm there, I will also shut down CUPSD:
sudo systemctl stop ssh.service cups.service cups.socket cups.path cups-browsed.service
sudo systemctl disable ssh.service cups.service cups.socket cups.path cups-browsed.service
Obviously, don't disable SSHD if this is a remote device. Instead, change the value of Port in /etc/ssh/sshd_config.
Running netstat again should show a cleaned up number of listening TCP ports:
sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 948/systemd-resolve
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN 1041/dnsmasq
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 948/systemd-resolve
tcp6 0 0 :::5355 :::* LISTEN 948/systemd-resolve
Setup Cowrie
Cowrie must not be run as root. It is typically run with a user that has no special permissions, and which isn't in the sudo group. To do this, run one of the following commands:
sudo adduser --home /home/cowrie --shell /usr/bin/fish cowrie
sudo adduser --home /home/cowrie --shell /bin/bash cowrie
Install the required packages needed to run Cowrie:
sudo apt-get install \
authbind python-zope.interface python-twisted \
python-crypto python-cryptography python-pyasn1 \
python-gmpy2 python-openssl python-configparser \
python-service-identity python-dateutil
Because low-numbered ports are normally reserved, and Cowrie doesn't run as root, authbind will be used to bind to ports 22 (SSH) and 23 (Telnet). Setup authbind by running the following commands:
sudo touch /etc/authbind/byport/22
sudo touch /etc/authbind/byport/23
sudo chown cowrie:cowrie /etc/authbind/byport/2*
sudo chmod 770 /etc/authbind/byport/2*
Create a terminal window and login as the new cowrie user:
sudo --login --user cowrie
As the cowrie user, checkout the latest copy of cowrie source code from GitHub:
cd ~
git clone https://github.com/micheloosterhof/cowrie.git
cd cowrie
As the cowrie user, run the following commands:
cp cowrie.cfg.dist cowrie.cfg
cd data
ssh-keygen -t dsa -b 1024 -f ssh_host_dsa_key -N ''
cd ..
Edit start.sh and modify the AUTHBIND_ENABLED line at the top to enable authbind:
AUTHBIND_ENABLED=yes
Edit cowrie.cfg and make the following changes:
At this point, you can start the honeypot. As the cowrie user, run the following commands:
cd ~/cowrie/
./start.sh
This will have started the cowrie service in the background. Check to see that you now have a python process listening on ports 22 and 23:
sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 902/systemd-resolve
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN 1024/dnsmasq
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 902/systemd-resolve
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 32461/python
tcp 0 0 0.0.0.0:23 0.0.0.0:* LISTEN 32461/python
tcp6 0 0 :::5355 :::* LISTEN 902/systemd-resolve
Honeypot users
The usernames and password information is stored in ~/cowrie/data/userdb.txt. You can add usernames, passwords to accept, and passwords to reject.
For example, the default userdb.txt file contains the following:
cd ~/cowrie/data/
cat data/userdb.txt
root:x:!root
root:x:!123456
root:x:*
richard:x:*
richard:x:fout
This tells Cowrie to accept the username root as long as the password isn't root or 123456.
From past experience, usernames that work well on a honeypot include:
- root
- admin
- deploy
- support
- zabbix
- git
Adding a new user requires modifying the following:
- data/userdb.txt
- honeyfs/etc/group
- honeyfs/etc/passwd
- honeyfs/etc/shadow
- data/fs.pickle
The "standard" text files are simple enough to manage. The only trick is the fs.pickle file. The tool bin/fsctl is used to modify fs.pickle. For example, to add a user named "support" with a UID and GID of 1002, you need to run the following commands:
cd ~/cowrie/
bin/fsctl data/fs.pickle
cd /home/
mkdir support
chown 1002 support
chgrp 1002 support
exit
Stop and restart Cowrie for it to pick up the new fs.pickle.
Session logs
Log files are stored in log/, but of particular interest are the session logs stored in log/tty/. These logs can be played back using the bin/playlog tool to see what was typed in telnet and ssh sessions.
For example:
cd ~/cowrie/
ls -l log/tty/
-rw------- 1 cowrie cowrie 2042 Oct 22 04:06 20161022-040606-30503818-0i.log
-rw------- 1 cowrie cowrie 2369 Oct 22 04:12 20161022-041142-a40464d3-0i.log
-rw------- 1 cowrie cowrie 1654 Oct 22 04:17 20161022-041719-4fb2575b-0i.log
...
bin/playlog -m 1 -c log/tty/20161022-040606-30503818-0i.log
Expose the honeypot
The only thing left at this point is to expose the honeypot to the internet. Once I configured my router to place the honeypot in the DMZ, it took 110 seconds for the first "attack" to take place.
A live view into the log to see how the honeypot is accessed and/or compromised is easy to start:
tail -F /home/cowrie/cowrie/log/cowrie.json
{"eventid": "cowrie.session.connect", "message": "New connection", "src_ip": "114.33.195.137", "dst_port": 23, "dst_ip": "192.168.1.33"}
{"eventid": "cowrie.login.success", "username": "root", "message": "login attempt [root/xc3511] succeeded", "src_ip": "114.33.195.137", "password": "xc3511"}
{"eventid": "cowrie.command.input", "message": "CMD: sh", "src_ip": "114.33.195.137", "input": "sh"}
{"eventid": "cowrie.command.success", "message": "Command found: sh ", "src_ip": "114.33.195.137", "input": "sh "}
JSON log entries
The JSON log entries can be easily stored in a database for further analysis. I created a table in my PostgreSQL database where I store all of the events, and wrote a simple shell script to parse the JSON log files and insert records into the database. This doesn't have all of the possible available fields, but most of them, and certainly all of the ones that I found were interesting:
DROP TABLE IF EXISTS honeypot_log;
CREATE TABLE honeypot_log
(
id BIGSERIAL UNIQUE PRIMARY KEY,
eventid TEXT NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
session TEXT NOT NULL,
duration NUMERIC NULL,
system TEXT NULL,
message TEXT NULL,
src_ip INET NULL,
dst_port INTEGER NULL,
input TEXT NULL,
username TEXT NULL,
password TEXT NULL
);