Fun with Python powered telnetd honeypot

Reason: hardening, serendipity and curiosity

As you already know, in the past weeks I hardened all of my boxes: while doing it, I flushed all iptables/ipfw rules, changed the default policy to DROP and take it from there to enable every rule as soon as I need it. Whilst Ubuntu uses ufw as a fronted for iptables, Fedora uses firewalld.

After setting up UFW, by looking at journalctl I can see all rejected connections, like:

Sep 03 11:54:16 -- kernel: [UFW BLOCK] IN=eth0 OUT= MAC=XX SRC=XX DST=XX LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=24286 DF PROTO=TCP SPT=36864 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0

As we all know, Internet is a wild place. In this particular case, someone was trying to connect to my box on port 23/tcp (telnetd, is still there someone who uses it?).

My curiosity begin to increase. Let’s have a look on which ports I rejected most of the connections:

/var/log # zgrep -ho "DPT=\w*" syslog* | cut -d "=" -f 2 | sort | uniq -c | sort -nr | head -n 10
    # no. of attempts | port
   1009 23
    969 3128
    330 22
    248 8080
    168 80
    158 5060
    151 3389
    111 1825
     94 1433
     77 123

(as I am running an httpd-ssl server on this host, connections to 443/tcp port are not showed).

Idea

Ok, so mostly of the wild connectors out there try to telnetd to my host (and all other hosts on the Internet). Again, my curiosity prevails: how about a fake telnetd server written in Python with twisted? As I always wanted to have a look with twisted, seems a good idea. The main idea here is to write a simple telnetd server that:

  • shows the root prompt and waits for commands
  • answers with fake answers to some UNIX commands (like uname and id)
  • answers to all other commands with Command not found or with nothing (like that the command was accepted). The choice between answering in the former way rather than the latter is random
  • record everything that is written by the attacker

This is a very simple and diminished concept of an Honeypot and leads to the code I published the code on GitHub under telnetd_honeypot.

Just for the sake of increased security, I did not want to run this program as root (not because I do not trust it, just because it’s a bad practice!). But we need to run it as root, because we need superuser powers to open a listening socket on all ports <1024, especially 23/tcp.

Sounds like a dead end? Not at all. Meet rinetd. We set up a bounce redirection from 23/tcp to the port on which our basic honeypot is listening (8023/tcp), launched by an unprivileged user (again: for security. Feel free to spin up a Docker container just to launch the honeypot).

Demo

% python telnetd.py &
[1] 15171
% telnet localhost 8023
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
/ # uname -a
Linux f001 3.13.3-7-high-octane-fueled #3000-LPG SMPx4 Fri Jun 31 25:24:23 UTC 2200 x86_64 x64_86 x13_37 GNU/Linux
/ # id
uid=0(root) gid=0(root) groups=0(root)
/ # ls
/ # ps auxw
bash: ps: command not found

Results

The results are quite fascinating. By analizing our file produced by our honeypot runned just for 3 days we can see the most typed commands on the other side of the client:

~ % cut -d " " -f 6- telnetd_honeypot.log | sort | uniq -c | sort -nr | head -n 3  
921 sh
918 /bin/busybox ZORRO
879 root

We might notice that most of the lines are common passwords guessing, while the busybox invocation with the parameter ZORRO is mysterious: even Googling, I have no clues about it. Sounds like a custom firmware? There are also multiple attempt to inject a shellcode (which I am not publishing for obvious reasons).

There are also funny entries:

08/20/2015 12:43:10 AM INFO: 79.x.x.x knock knock neo

Anyone else has seen Neo?

The results are pretty interesting and deserve a further investigation. Upon running just for 3 days, I gather enough results to satisfy my curiosity. The honeypot described here is just a starting point, hoping to gather more contributors to this fascinating problem. With the addition of Docker containers, the future possibilities are quite infinite. Happy investigating!

Leave a Reply