Build a honeypot with real-world alerts
Seeing Is Believing
If you manage systems or get excited about security, like I do, you probably have an Intrusion Detection System (IDS), an ELK (Elasticsearch, Logstash, and Kibana) syslog server front end, performance monitoring, and a plethora of other dashboards. The first week your IDS or SIM is running, everyone watches it, trying to catch an invader in their enterprise. Then, when the sheer amount of data coming in overwhelms you, the systems are left to run in the dark recesses of your data center. During the 2013 hack of Target, numerous warnings from the IDS were ignored, which lead to a judge ruling in 2014 that banks could sue Target for losses [1].
In the medical field, this is called alert fatigue and is blamed for ignoring dangerous drug incompatibilities or even ignoring real health monitoring emergencies. You can help fight this by taking the alert off of the screen and into the real world with the following items:
- Raspberry Pi with SD card
- Rasp Pi Relay HAT [2] (Figure 1)
- Alarm: Anything with lights! I even used a light-up tin robot toy for a while
To be honest, it is also a fun way to show people outside of the security group that hacks are happening.
In this article, I build a standalone system (Figure 2) with some tools I collectively call honeyBot; however, it could certainly be deployed on multiple systems, because it is designed to be modular. Files are monitored by one process, and alerts are then sent by MQTT and stored in a SQLite database. The front end is a lightweight Flask app [3].
Setting up the honeypot comprises two main steps: system configuration and software deployment. To begin the system configuration, secure the Pi and set it up to log failed logins and Nmap scans by first creating an SSH key with the ssh-keygen
command (Figure 3); you will copy the public key and enforce key-based logins.
On the client, copy your public key file and test your login:
ssh-copy-id -i ~/.ssh/id_rsa_honeybot.pub pi@raspberrypi.local ssh pi@raspberrypi.local -i ~/.ssh/id_rsa_honeybot
This box is on the public Internet, so you will need keys to log in via SSH. To do so, edit sshd_config
, uncomment the line PasswordAuthentication
, and set its value to no
. After you have made the changes, restart the SSH daemon:
sudo service ssh restart
At this point, if you have any issues logging in, take a look at the documentation from the Raspberry Pi organization [4].
The next step in securing the Raspberry Pi and collecting data is to set up iptables by installing iptables-persistent
apt-get install iptables-persistent
and creating some rules. Although you can manually enter the rules, an online sample file [5] (Listing 1) makes it easy. Be sure to change the subnet mask on line 11 to your address space, so web console access is only allowed from your trusted space. It is a honeypot after all, so nothing is really trusted. The takeaway is the -j LOG
option (line 12), which logs port scanning behavior to a logfile with the iptables:
prefix.
Listing 1
iptable Rules
01 *filter 02 *filter 03 :INPUT ACCEPT [0:0] 04 :FORWARD ACCEPT [0:0] 05 :OUTPUT ACCEPT [125:13440] 06 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 07 -A INPUT -p icmp -j ACCEPT 08 -A INPUT -i lo -j ACCEPT 09 -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT 10 -A INPUT -p udp --dport 5353 -j DROP 11 -A INPUT -s <add your subnet> -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT 12 -A INPUT -m limit --limit 30/min -j LOG --log-prefix "iptables: " 13 -A INPUT -j REJECT --reject-with icmp-host-prohibited 14 -A FORWARD -j REJECT --reject-with icmp-host-prohibited 15 COMMIT
In the /etc/rsyslog.d/10-iptables.conf
file, modify rsyslog to log messages to its own file,
:msg,contains,"iptables: " /var/log/iptables.log
and then restart rsyslog:
service rsyslog restart
The :msg,contains,"iptables: "
option tells rsyslog to store alerts in iptables.log
. You can test this new setting by running Nmap from your remote machine and tailing the /var/log/iptables
file (Figure 4) with:
tail -f /var/log/iptables.log
For my environment, I wanted to disable IPv6 in /etc/sysctl.conf
, because my ISP was IPv4 only:
##ipv6 net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1
At this point, the Raspberry Pi is set up, so it is time to install the honeyBot prerequisites and then configure the software. The honeyBot software comprises three processes: honeyBotMon.py
, honeyMqtt.py
, and honeyWeb.py
. All of these and the startup scripts are available in the GitHub repo [6].
The Python tools require a few packages:
apt-get install python3-rpi.gpio daemonize mosquitto mosquitto-clients pip3 paho-mqtt flask maxminddb-geolite2geopandas pyshp shapely plotly psutil
Before installing the software, I'll review the function of each part of the system, so you can expand on it and make your install even better. The honeyBot tools are released under the GNU GPLv3, and code contributions are always welcome.
The Python program honeyBotMon.py
looks at two files: iptables.log
and auth.log
. The auth.log
file logs failed SSH logins. The iptables.log
file has information about port scans. Five scanned ports from a single host or one failed login calls the functions raiseAlert
and sendAlert
(Listing 2).
Listing 2
honeyBotMon.py Snippet
01 while(1): 02 time.sleep(args.delay) 03 line=sshFile.readline() 04 if line: 05 if "sshd" in line and "closed" in line and "preauth" in line: 06 srcIP=line.split()[8] 07 print(srcIP) 08 raiseAlert(relay) 09 sendAlert(args.server, srcIP) 10 11 line=iptablesFile.readline() 12 if line: 13 if "UDP" in line or "TCP" in line: 14 for words in line.split(): 15 if "SRC" in words: 16 srcIP=words.split('=')[1] 17 if "DPT" in words: 18 dPort=words.split('=')[1] 19 20 #count the number of ports keyed by src IP 21 if srcIP: 22 print("srcIP: {} dPort {}".format(srcIP, dPort)) 23 if srcIP not in srcIPs: 24 srcIPs[srcIP] = 1 25 else: 26 srcIPs[srcIP] += 1 27 28 if srcIPs[srcIP] == 4: 29 print("alert") 30 raiseAlert(relay) 31 sendAlert(args.server, srcIP) 32 srcIPs[srcIP] = 0 33 srcIP = None
The function raiseAlert
tells the relay to go high and low, making the emergency light flash:
def raiseAlert(relay): GPIO.output(relay,GPIO.HIGH) time.sleep(5) GPIO.output(relay,GPIO.LOW)
The function sendAlert
uses MQTT to send a message with the topic honeyBot/IP
to the MQTT listener locally or on another host:
def sendAlert(server, message): pub.single('honeyBot/IP', message, hostname=server)
The next piece, honeyMqtt.py
, listens for connections and writes them to an SQLite database (Listing 3), and the last piece is the web front end, honeyWeb.py
, which uses the flask
module for the alert display and uses GeoIP to geolocate the attackers. When the index page is hit, it will query the SQLite database and look up the location (Listing 4).
Listing 3
honeyMqtt.py Snippet
01 def on_message(mosq, userdata, msg): 02 print(msg.payload.decode("utf-8")) 03 now=datetime.datetime.now() 04 t=(msg.payload.decode("utf-8"),now,) 05 query='insert into honeyLog(ip, dateStamp) values(?,?)' 06 cursor=db.cursor() 07 cursor.execute(query, t) 08 db.commit()
Listing 4
Geolocating Attackers
01 for row in rows: 02 ip=row[1] 03 count=str(row[0]) 04 match = reader.get(ip) 05 if match: 06 try: 07 country=match['country']['names']['en'] 08 except: 09 country="unknown" 10 else: 11 country="unknown"
Now you need to set up your honeypot to run on boot. Copy the *.service
files to /lib/systemd/system
, and then enable them (Listing 5). You can now browse to the Rasp Pi IP address to view the alerts (Figure 5). Be warned, it is a self-signed key, so you will get a security warning.
Listing 5
Run honeyBot on Boot
wget https://github.com/joemcmanus/honeyBot/archive/master.zip unzip master.zip mkdir /var/honeyBot cp -r master/* /var/honeyBot cp startupScripts/*.service /lib/systemd/system systemctl enable honeyBotMon.service systemctl enable honeyMqtt.service systemctl enable honeyWeb.service
Electronics
To wire the Relay Hat you will need to pick a spot somewhere in the middle of the cord, cut one of the wires, and strip each end. Insert one end of each wire into the screw terminals of the relay labeled "Relay Ch1." One end of the wire should be in the outside terminal (rightmost if the screw terminals are facing you) and the other in the center terminal of the terminal (Figure 6). Keep in mind that you are using household current, so be careful! Be sure you have the alarm unplugged. I tinned the stranded copper wire so it did not fray when inserted into the relay.
After building this honeypot, set it up in a conspicuous location to highlight the threats a public-facing machine encounters – and provide a bit of fun. You can also see it in action on YouTube [7].
Infos
- Target hack: https://bits.blogs.nytimes.com/2014/12/04/banks-lawsuits-against-target-for-losses-related-to-hacking-can-continue/
- Relay HAT: https://www.amazon.com/Raspberry-Pi-Expansion-Module-XYGStudy/dp/B01G05KLIE/
- Flask web framework: https://www.fullstackpython.com/flask.html
- Passwordless SSH access: https://www.raspberrypi.org/documentation/remote-access/ssh/passwordless.md
- Sample iptables: https://github.com/joemcmanus/honeyBot/blob/master/sampleIptables
- honeyBot on GitHub: https://github.com/joemcmanus/honeyBot
- honeyBot in action: https://youtu.be/CRGIwtG3IiA
Buy this article as PDF
(incl. VAT)