../
Looking for a senior C++ dev? I'm looking for work. Hire me!

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

(I strongly recommend trying out fish as a shell if you've not tried it yet.)

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:

Adding a new user requires modifying the following:

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 );
Last modified: 2016-10-26
Stéphane Charette, stephanecharette@gmail.com
../