notes from my honeypot project
b608c672 — paula 2 days ago
fixed readme
added useful one liners I used a lot


browse  log 



You can also use your local clone with git send-email.

#customized honeypot with cowrie

#1. Creating the basic honeypot

Following this manual I configured a cowrie environment in a VPS:

1.1 Changing the Port 22 to port between 49152 and 65535.

sudo nvim /etc/ssh/sshd_config

1.2 Restart service

sudo systemctl restart ssh
sudo systemctl status ssh

1.3 Install software

sudo apt install -y python-virtualenv libssl-dev libffi-dev build-essential libpython3-dev python3-minimal authbind git

1.4 Create passwordless user cowrie

sudo adduser --disabled-password cowrie

1.5 Installing authbind, running the command and changing ownership

sudo apt install authbind
sudo touch /etc/authbind/byport/22
sudo chown cowrie:cowrie /etc/authbind/byport/22

1.6 Changing permissions

sudo chmod 770 /etc/authbind/byport/22

1.7 Login as cowrie and going "home"

sudo su cowrie
cd ~ 

1.8 Clonning the cowrie repo and entering it

git clone https://github.com/micheloosterhof/cowrie
cd cowrie

1.9 Create new configuration

cp etc/cowrie.cfg.dist etc/cowrie.cfg

1.10 Edit the file and replacing 2222 with 22 in listen_endpoints

nvim etc/cowrie.cfg

in the file:

listen_endpoints = tcp:2222:interface=


listen_endpoints = tcp:22:interface=

1.11 create virtual environment and enable it

virtualenv cowrie-env
source cowrie-env/bin/activate

1.12 Updating pip

pip install pip3

1.13 Install requirements

pip3 install -r requirements.txt

1.14 Starting cowrie

bin/cowrie start

1.15 Checking the honeypot

netstat -tan

#2. Customizing the whole thing

2.1 Copying a docker image

In my case I wanted to imitate an IoT Linux device to investigate ssh bruteforce related to cryptomining. So I'm copying a docker system based on openwrt. First I logged off cowrie and in the default sudoer, I performed:

$ docker container create -i -t --name mycontainer shellspec/openwrt
$ for i in proc usr sbin sys lib etc bin; do  sudo docker cp mycontainer:$i /tmp/picklefs; done

Now, make sure you are in the cowrie session first. sudo su cowrie, for this you might need to perform from sudo chmod o+r in some files of the filesystem.

Now I have a copy of the whole openwrt filesystem. In any case I make sure to add whatever is necessary so to fit the addecuate format, as described in this issue. I want to create this filesystem in cowrie so:

$ bin/createfs -l /tmp/picklefs -d 6 -o /home/cowrie/cowrie/share/cowrie/honeyfs.pickle

The default pickle system is fs.pickle, I did a backup of it and changed the name of the new one:

$ cd /home/cowrie/cowrie/share/cowrie/
$ mv honeyfs.pickle fs.pickle

I also needed to copy in /cowrie/cowrie/etc/ the filesystem, so I used the /tmp/ copy for that. If you need to change something and then re-compile the pickle, I recommend using the honeyfs directly.

$ cd /home/cowrie/cowrie/honeyfs
$ rm rf *
$ cp /tmp/picklefs .

The filesystem is copied but I wanted to add some stuff. In the case of cryptominers, most of them attempt a few things:

  • Deleting /etc/ld.so.preload
  • Attempting ssh bruteforce using known_host
  • Deleting competition
  • Using wget and curl to donwload further scripts

So I wanted to put some stuff around to make it "easier" for a cryptominer to be comfortable.

NOTE: From the interactive console you can create files but for the contents you have to edit the honeyfs filesystem and re-compile de pickle!


First creating an empty ld.so.preload file. I used a nice tool of cowrie to interact with the fake filesystem. In the cowrie repo home directory:

$ sudo su cowrie
$ source cowrie-env/bin/activate
(cowrie-env) cowrie@<myvps>:~/cowrie$ ./bin/fsctl share/cowrie/fs.pickle

A shell should open, and then I went like:

Kippo/Cowrie file system interactive editor
Donovan Hubbard, Douglas Hubbard, March 2013
Type 'help' for help

fs.pickle:/$ cd /etc/ 
fs.pickle:/etc$ touch ld.so.preload

2.3 Generating ssh content On cowrie user without the source activated, in /home/cowrie/cowrie/honeyfs:

$ mkdir .ssh
$ mkdir .ssh/config
$ cd .ssh/config
$ ssh-keygen

in the dir and file choice, I choosed the current folder. Later I tried to ssh a beacon address using the same key and saved the known_hosts file in the same folder, too. I went to the shell and added the same files.

2.4 Deleting competition and configuring wget and curl

In /cowrie/share/cowrie/txtcmds/bin created the files curl and wget with fake error messages:

$ touch curl wget
$ nvim curl
$ nvim wget

Since I was already doing this I added ufw too. In enable file I added fake services with names commonly seen in other cryptominers, so it's seen if any enumeration is attempted.

#3. Testing

When everything was done, I tested it. First, activating the virtualenv and then in the cowrie repo directory:

$ bin/cowrie stop
$ bin/cowrie start

And attempted to connect using another console:

$ ssh -p 22 root@<myip>

I played around a bit in the fake shell and exited. Then I took a look at cowrie/var/log/cowrie. After a day I saw in the logs how some IPs attemped to connect so I created a script to extract those IP's directly:

yesterday=$(date -d "yesterday 13:00" '+%Y-%m-%d')
cat cowrie.json.$yesterday | grep "New connection:" > connections


while read -r line; do

#	echo $line
        ejem=$(echo $line)   

#	echo "step1 = $step1"
#	echo "step2 = $step2"
        echo $step2 >> collectedIPs_raw
done <connections

awk '!a[$0]++' collectedIPs_raw > collectedIPs

rm collectedIPs_raw
rm connections

I then investigated the IPs in collectedIPs, ignoring my own. I also wanted to investigate commands so I did:


yesterday=$(date -d "yesterday 13:00" '+%Y-%m-%d')
cat cowrie.json.$yesterday | grep "input" > commands

In my local computer I took those files:


if [ "$1" = "IPS" ]; then
	echo "collecting IPs"
	scp -P <my_real_port> <myuser>@<myip>:/home/cowrie/cowrie/var/log/cowrie/collectedIPs .
elif [ "$1" = "commands" ]; then
	echo "collecting commands"
	scp -P <my_real_port> <myuser>@<myip>:/home/cowrie/cowrie/var/log/cowrie/commands .
	echo "ERROR"

So all I had to do is:

$ myscript IPS


$ myscript commands


As I said, most cryptominers try to delete other competitors. I created a realistic kinsing sample which downloads a "cryptomining binary" from a webserver I'm also serving myself. The rest of the sample looks exactly like a real kinsing miner downloader.

The binary is an elf compiled from bash which has some real but safe miner string lines that trigger YARA alerts of miners in linux, but also attemps to ssh the honeypot shell in a oneliner. I uploaded both on VT, the fake downloader and the fake binary :)


So far, a few IPS attempted to connect, most of them are digital ocean IPs that are related to malware and sshbrute forcers. A couple of them attempted to TLS handshake as an attempt to connect using https protocol.