Create a Network Honey Pot with (Python) Sockets

Use Python3 sockets to create a honey pot for the detection of malicious activity on a network

Overview

A malicious network actor (e.g., malware or an intruder) on a local network will typically strive to find open ports. One of the ways to detect this activity is to create a honey pot. This is an open port disguised as a legitimate service for the purpose of catching and reporting malicious / unwanted activity.

In this article we use the Python socket interface to develop a honey pot. There are many different paths to take when developing a honey pot. One can go as far as fully emulating a particular service (i.e., ftp) and allowing the bad actor to download false or potentially dangerous files (e.g., launch malware on your neighbor's network in retribution for him or her jumping on yours!).

In this article, we're just going to meet the following goals:

  • Create a listening port on an IPv4 network known port (telnet) and alert on a basic TCP SYN/ACK handshake.
  • Show that nmap detects the port (our honey pot)
  • Alert us if our honey pot port is probed / scanned (by nmap)

With just this basic, simple tool, we can become alerted to unwanted activity on our network.

Configuration

We develop and test our honey pot using two Linux systems. The client system (Ubuntu 16.04) is used to run nmap and tcpdump. The server (embedded Linux 4.11) is used to run our python3 honeypot.py script as root.

The Python socket interface is modeled after the Unix socket API. In working with Python sockets, you will probably find yourself often referring to Linux man pages for various definitions.

And as pointed out in the Python socket documentation, the socket module / interface depends on calls to the underlying operating system, so your usage of the provided example may work differently ( or not at all) on a different system.

Preliminaries

Let's start out by verifying that nmap and tcpdump are working properly on our client system by confirming that an ftp server is running on our embedded Linux server. Shell 1 will be used for nmap and Shell2 will be used for tcpdump.

shell 1
$ nmap 192.168.3.200 -p 21

Starting Nmap 7.25SVN ( https://nmap.org ) at 2017-05-07 15:52 EDT
Nmap scan report for Server (192.168.3.200)
Host is up (0.00023s latency).
PORT   STATE SERVICE
21/tcp open  ftp

Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds
shell 2
$ sudo tcpdump -Xvn -i enp2s0 host 192.168.3.200 and port 21
...
<packet dump>
...

It's a good idea at this point to play around with different nmap options (e.g., -sV: determine service) and also try this with the ftp server not running. If you're not running an ftp server, then just run nmap against your server to see what ports are open.

Socket basics from the shell

The Python socket documentation is extensive and provides enough examples that will get you started. For our purposes, let's show the setup of a basic listening port using the Python 3 shell / interpreter:

$ python3
Python 3.5.2 (default, Mar 29 2017, 18:58:38)
...
>>> from socket import socket, AF_INET, SOCK_STREAM
>>> sk=socket(AF_INET,SOCK_STREAM)
>>> sk.bind(('192.168.3.200',23))
>>> sk.listen()
>>> conn,addr = sk.accept()

This last line should now block, waiting for a client to connect. Go back to shell 1 on the client and run nmap with "-p 23".

$ nmap 192.168.3.200 -p 23

Starting Nmap 7.25SVN ( https://nmap.org ) at 2017-05-07 16:00 EDT
Nmap scan report for Server (192.168.3.200)
Host is up (0.00020s latency).
PORT   STATE SERVICE
23/tcp open  telnet

Nmap done: 1 IP address (1 host up) scanned in 0.02 seconds

Go back to your Python shell on the server, and the command line should have returned. Type the following into the shell:

>>> print('alert ' + addr[0] + ' has connected with us')

Bringing it together

The source code for our honeypot.py script is provided below. Run the script on your server and provide the IP address that matches the interface you're listening on using the '-a' option.

# ./honeypot.py -a 192.168.3.100

Now run nmap to scan the system at port 23:

$ nmap 192.168.3.200 -p 23

Starting Nmap 7.25SVN ( https://nmap.org ) at 2017-05-07 21:06 EDT
Nmap scan report for Server (192.168.3.200)
Host is up (0.00021s latency).
PORT   STATE SERVICE
23/tcp open  telnet

Nmap done: 1 IP address (1 host up) scanned in 0.02 seconds

You should see the honey pot report the scan as shown below:

# ./honeypot.py -a 192.168.3.100
honeypot has been visited by 192.168.3.36

You can also try your honey pot using the telnet client. It should close the port after the user hits the enter key (return).

Source Code

python3 script, honeypot.py
#!/usr/bin/env python3  
""" 
Copyright 2017 Mind Chasers Inc,
file: honeypot.py
Demo code.  No warranty of any kind.  Use at your own risk
"""
import sys
import argparse
from socket import socket, AF_INET, SOCK_STREAM, MSG_WAITALL,getaddrinfo

VERSION = '0.0'
welcome = b"Ubuntu 16.04.2 LTS\nserver login: "

def send_email(src_address):
    """ Todo: send an email if we're scanned / probed on this port """
    pass

def honeypot(address,port=23):
    """ create a single Threaded telnet listen port """
    try:
        ski=socket(AF_INET,SOCK_STREAM)
        ski.bind(('192.168.3.200', port))
        ski.listen()
        conn,addr = ski.accept()
        print('honeypot has been visited by ' + addr[0])
        send_email(addr[0])
        conn.sendall(welcome)
        while True:
            data=conn.recv(1024)
            if data == b'\r\n':
                ski.close()
                sys.exit()
    except Exception as e:
        #print('honeypot exception : {0}'.format(e)) 
        ski.close()
        sys.exit()
    
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='honeypot prototype',
                                 epilog='Version: ' + str(VERSION))
    parser.add_argument('-a','--address',help='server ip address to use',action='store')   
    args = parser.parse_args()
    
    honeypot(args.address)




Issues

You now have the basics of a useful honey pot, but there is still much that can be added and should be considered:

  • Keep in mind that a honey pot is basically a fake network service, and they're easy to write. The other side of this story is to remind yourself to not blindly trust network services since providers and hackers can replace or modify them with a compromised implementation for the purpose of stealing data.
  • We picked telnet because it's simple to emulate and test. However, you NEVER want to actually have a telnet server running on one of your hosts. Telnet exchanges data across the network in the clear, which means that any eavesdropper can sniff all data exchanged including user credentials.
  • If your goal is to create an elaborate honey pot that very closely mimics the behavior of a service, then it may be better to just start with the existing source (e.g., vsftp) and patch in your alerts.
  • Our example is single threaded, which may be preferred. Consider the dangers of a multi-threaded honey pot that sends email alerts on each access and the potential to create denial of service attacks by repeatedly stimulating the honey pot service. At the very least, you'll want some sort of rate limiting in a multi-threaded honey pot.
  • Consider turning your honey pot script into a daemon and using a cron job to check its status & restart it if necessary. References are provided below for this.
  • You may see something like the following between invocations: "honeypot exception : [Errno 98] Address already in use". This can be expected while waiting for the OS to close the port. Give it a little time and try again. If you're stuck, post a comment below

References

Help us improve this article by adding your comment or question:

email addresses are neither displayed nor shared