Creating honeypots using Docker
What's a honeypot?
A honeypot is computer system running vulnerable software deliberately to lure attackers to the system and to log their actions. Honeypots are useful for detecting emergent cybersecurity threats, analysing the attackers behaviour and discovering 0-day exploits. The most popular honeypot software include Kippo, Glastopf, Dionaea and Thug.
Why create a new one?
While there are several different honeypot software available for free, these honeypots try to emulate a live system by providing and presenting fake services to the attacker. This method works against automated attacks, but fails against a sophisticated manual attack. Detecting Kippo SSH Honeypots describes several techniques which could be used to reveal to the attacker that the targeted system is indeed a honeypot. Most of these methods have been already patched, but nonetheless it is relatively easy to find alternatives for example: checking file checksums, looking at system statistics or checking whether the network connection works by sending a ping probe to an attacker owned system. Similar techniques can be employed against the other honeypots as well.
The other issue with this approach is that the honeypots are limited to emulating one or more specific services. I cannot install any custom software I want to, because I either have to create an emulated version for that software or look for a honeypot that implements it.
Solving these issues
Instead of trying to emulate every possible quirk of the faked system, it is more preferable to grant access to a real system so the attacker has no way of knowing whether he or she is logged on to a honeypot or not. Securing a real system is not easy, but it can be done as there are several sites similar to honeypots that do this properly. The best example is online code compilers, which enable remote code execution, but are secured in a way that the attacker cannot disrupt the service or do real damage against someone.
Our solution using Docker
Our solution uses xinetd to spin up a new container for each connection. The daemon has to be configured to listen on all ports which are bound on the container so it can trigger the container creation script. After launching the instance we introduce an iptables rules to redirect all traffic from the attackers ip to the container and to firewall the containers from each other. This is required as some services open up additional listening ports after accepting a connection. This way we can also skip invoking xinetd for a second time. An attacker connecting from a specific IP for the second time lands on the same container he/she used before. The containers are destroyed after a specified time using a cron script and the iptables rule is deleted.
We want to log the actions of the attacker in a way that doesn't require modification to the containers configurations and it is impossible to disable from within the container. Since docker run on the same kernel as the host machine, we can use kernel level logging to see what is going on inside the container. An off the shelf solution is to install the auditd daemon and configure it to log execve system calls. Unfortunately auditd doesn't support kernel namespaces yet, so the logs cannot be filtered for a specific container. Another option which solves this problem is to configure the containers to forward their syslog data to the host, but this can be disabled from the instance if the attacker has root rights, so some SELinux/RBAC trickery may be needed prevent this from happening.
The containers can be completely customized; they can be SSH honeypots, web honeypots etc. The only change we have to make is to add the listening ports to the xinetd configuration. Depending on the services custom logging may be required to provide detailed logs.
The attacker can perform resource-exhaustion attacks against the host if docker is not configured properly. These attacks typically include fork bombs (and other memory hogs) and creating large amounts of logs. Memory exhaustion can be solved by limiting the available memory for a container to a predefined amount.
Network attacks from the container
Each container is configured with an inbound and an outbound network quota to prevent the attacker to perform DoS and network attacks against other hosts. Outbound connections can be disabled completely using iptables if needed, but that can reveal that our host is a honeypot.
Want to run your own?
If you want to run your own docker based honeypot grab the scripts for my SSH honeypot from GitHub and follow the instructions in the readme.