A few weeks ago I became curious as to what types of credentials were being attempted on SSH. I came up with the idea of creating a honeypot and capturing what credentials were attempted, when they were attempted and where the attempts originated from.
What Is A Honeypot?
Some of you may not be aware of what a honeypot is. The following is taken from the Wikipedia definition:
In computer terminology, a honeypot is a computer security mechanism set to detect, deflect, or, in some manner, counteract attempts at unauthorized use of information systems. Generally, a honeypot consists of data (for example, in a network site) that appears to be a legitimate part of the site, but is actually isolated and monitored, and that seems to contain information or a resource of value to attackers, who are then blocked. This is similar to police sting operations, colloquially known as “baiting,” a suspect.
In short, a honeypot is a system that appears to provide a service to either attract attention away from a real resource or to capture details of nefarious attempts made upon it.
A word of caution. I would not have tried this on a local machine if it were not for 1 fact. I had a spare broadband connection that I could dedicate to the project. This ensured that if something went wrong, no other devices could be compromised. If you follow the below steps you do so at your own risk.
How I Setup The Honeypot
There are a number of popular packages that provide SSH honeypot functionality (such as Cowrie). This was intended partially as a learning experience, therefore, using such a package would have negated from this objective. So where possible I fashioned my own tools for the task.
Choosing A Device
The first decision I had was to choose the device that was going to act as a honeypot. I have numerous old PC’s laying around however it would have been overkill to dedicate one of these to the project. Another choice I have was the Raspberry Pi, I have quite a quantity of these lying about, they take up little room, they require few resources (such as power) and the form factor is perfect so I can tuck it away easily.
I did not need any specific from a distribution that would be installed on the Raspberry Pi, therefore, I stuck with Raspbian. I am not a big fan of Noobs, therefore, I installed a headless copy Raspbian directly (if you are unsure how to do this I have an article explaining here).
There is no reason why this could not work on a standard PC with an operating system such as Cent O/S or Ubuntu, you may need to tweak a few things.
I knew I wished to capture the details of any request and decided that utilizing a Pam module would be my best choice. I was unsure if such a module existed but (as per above) this is a learning exercise, therefore decided to build a basic module myself. The module was written in c and stores the details in an SQLite database.
This module purposely does not allow any login at all (not even from me, if I needed access I would hook up a monitor and keyboard). As I was not looking to allow login attempts to go further than checking the credentials, I only implemented the ‘ pam_sm_authenticate’ method for the Pam module. The source code can be found on Github.
Props go to an article entitled “Writing a Linux PAM module” from the Fedetask Useless Blog. I found this article as well as the other associated articles very useful in understanding how PAM worked.
After configuring my SSH server to use the newly created pam module I found a problem. Some requests were storing empty credentials or worse populated with “Incorrect” (or a substring matching the length of the password). This, of course, was a show stopper.
Upon investigation, I found that the source code for OpenSSH contained a function called ‘fake_password’ in auth-pam.c. This was responsible for helping guard against timing attacks and obfuscated the password. To resolve my issue I had to remove this code, compile my own version and install on the Raspberry Pi (source code).
Lastly, I wished to store the login credentials offsite. This was in case something happened to the Pi that made it impossible for me to retrieve the date. Therefore I created a python script to upload the requests to an AWS API endpoint. This was as a backup plan.
So that the login attempts could be stored on AWS there was a 3 stage set up.
- DynamoDB database set-up to store the data
- A Lambda function created to action any put requests
- API gateway to allow outbound connections in an easy manner to the Lambda function.
To aid in security I ensured that the API Gateway required a key for any requests. This would help stop any random requests being made.
I am not currently going to go into detail on how AWS was setup as this would require an article in itself.
Installing The Honeypot
Each of the technologies above is currently hosted on Github and each has its own installation methods and scripts however I have put together a very crude installer on Github.
There are a couple of steps missing as per the README file. Such as configuring SSH to use the PAM module and to add execution of the python script in cron.
Once installed you can leave it be, provided the requests do not overload the logger.
What I Learnt
When creating the honeypot I decided early on that I was going to log the requests and pass them to AWS In hindsight this was probably not required and actually caused overhead. For example, the honeypot received several prolonged attacks. During each of these attacks, the script that was uploading to AWS could not keep up (I intentionally throttled it). I had to increase the number of requests it would upload at any given time to keep up several times. If I were to do it again (who am I kidding, when I do it again) I will drop the step of logging to AWS, if anything I will back up the whole database file, potentially still on AWS.
Learning how PAM worked was quite interesting. The same module that I created should work fine with other services such as MySQL which is potentially my next project. It would be a trivial task to port this over to something like MySQL providing there are no gotchas similar to the fake_password function in SSH.
If you are interested in my findings from running the honeypot you can read about it in my article entitled “I Opened My Connection To SSH Attacks, And These Were The Requests I Saw”.
A few errors were found in the honeypot-installer repository. These have now been resolved and should be functional. As part of the changes I have also removed the AWS code from the installer. You can still add this if you would like however as mentioned I feel this was not required.
The openssh repository has also been updated to the latest code on Master for the official openssh repository.