Building a Simple HTTP Honeypot

jon heise
EvilCouncil
Published in
3 min readJul 11, 2022
The Go Gopher emerges suspiciously from a pot of honey

Honeypots are a useful tool to track scanners and new attack vectors. There are plenty of existing honeypot solutions readily available, some more general purpose, others extremely application specific. Even with all of these options, building one from scratch gives additional insight into what can be detected with a honeypot.

Getting Started

Any language that can listen on a socket can be used to build a honeypot, however some languages and frameworks make this task more straight forward that others. This tutorial will use Go, it provides a very robust HTTP library and server in its standard library, net/http. Additionally the server provided by net/http performs comparably to other HTTP servers like Nginx and Apache.

Basic HTTP Server

The following code will launch a web server on port 8080 and send a response

This great, a full web server in 13 lines of code, any path that is requested be processed by HandleIndex, time to expand that function collect intelligence.

What to capture

Looking at the arguments for HandleIndex, there is w ResponseWriter which sends data back to the client, and req Request which contains all of the data for the client’s request. Taking a look at the docs for request, there is a plethora of readily useful fields to record as part of a honeypot.

  • RemoteAddr — What IP made this connection
  • Method — What method is being used by the client, normally this will be a GET or POST request
  • RequestURI — What path is being requested
  • Header — What headers were sent by the client, since this is easily user
  • User Agent — What client is in use
  • PostForm — If this was a POST or PUT request, what additional data was sent

Additional data points to capture that are not part of the Request struct

  • Event Time — when was this request made, ideally store this as a unix timestamp and the honeypot server should be using UTC as its timezone
  • Honeypot Name — If you are running more than one honeypot, identifying your log source can an interesting feature to track .

Collecting data

With fields identified all of the intelligence can be extracted and prepared for logging

Logging, and the benefits of structured logs

Data has been extracted from the request and prepared for logging in a Record struct, now its time to write this to a log file. Utilizing a structured log format like JSONL making parsing the file later a much easier task. Logging with JSONL is very straight forward, convert a record struct into its json representation and write it to the log file.

Neo is questioning Morpheus if structured logs make it easier to write regex, Morpheus explains that structured data like JSON can be parsed using a standard parsing library.

The complete honeypot

Here’s all of the code together:

Check out a more full featured version here and the matching container here.

Recent traffic

Looking at 30 days worth of a traffic for a deployed honeypot shows a few trends.

Top 10 Scanners

Given that the IP for the honeypot has not been published anywhere and its serving a web page that simply displays “This is a honeypot”, its safe to say all of the above traffic is from scanners. Two of these scanners are easily out pacing the rest.

Top 10 URLs

Taking a look at the top 10 URLs, lots and lots of credential scanning, in future serving a canary token for these URLs might get some additional interesting data.

In Conclusion

  • Golang makes a great passive honeypot
  • Write logs into a structured format, save time parsing them later.
  • Scanners really want to find some credentials

--

--