We mentioned that one of the disadvantages of low-interaction honeypots is their lack of fidelity. They cannot be fully compromised by an adversary, and because of that, they do not yield as much information as a high-interaction honeypot that an adversary can take over completely. This makes it easier to protect your low-interaction honeypots. There are less threats for you to worry about. For example, emulated services usually do not allow an attacker to install a packet flooder and launch denial of service attacks from your computer. That is assuming that the honeypot you are running is completely secure. If there was a vulnerability in the honeypot itself, your low-interaction honeypot could all of a sudden turn into a high-interaction honeypot, and that is something we really would like to avoid. In the following, we will present a few security-enhancing procedures that should help making a compromise of your honeypot less likely.
Using the chroot command, it is possible to restrict an application to a small portion of the file system. This happens by changing the root of the application's filesystem to a specific directory. Once chroot has been applied, the application can no longer access any files but those in the provide directory. For example, OpenBSD runs parts of OpenSSH chrooted to /var/empty; as the name suggests, the directory is completely empty. An adversary who gets control of OpenSSH's network process will not be able to see any files.
Here is a quick example that you can try yourself if you are running a BSD variant. Type the following commands as root:
# mkdir -p /tmp/test/bin/ # cp -p /bin/ls /tmp/test/bin/ # cp -p /bin/sh /tmp/test/bin/ # chroot -u $(whoami) /tmp/test /bin/sh |
When you execute the chroot command, it creates a new process whose file system is rooted in /tmp/test/. That chrooted process will not be able to see anything that lives outside of that subdirectory. The shell that you specify with /bin/sh is really the shell that we just copied to /tmp/test/bin/sh. On OpenBSD, you are going to see something like this:
/bin/sh: No controlling tty (open /dev/tty: No such file or directory) /bin/sh: warning: won't have full job control $ |
If you are running on a Unix system that does not ship with any static binaries like Linux, creating a chroot jail becomes a little bit more difficult. The preceding procedure is going to fail miserably because the shell cannot find its shared library. Linux's chroot utility is also quite primitive compared to the BSD variant. The following commands might work for you:
# mkdir -p /tmp/test/bin/ /tmp/test/lib/ # cp -p /bin/ls /tmp/test/bin/ # cp -p /bin/sh /tmp/test/bin/ # cp -p $(ldd /bin/sh | sed -e "s/.*\s\//\//" -e "s/\s.*//") /tmp/test/lib/ # cp -p $(ldd /bin/ls | sed -e "s/.*\s\//\//" -e "s/\s.*//") /tmp/test/lib/ # chroot /tmp/test /bin/sh |
The main difference is that in addition to providing the binaries for the shell and the ls command, we also need to install the shared libraries that they depend on. We can use the ldd utility to tell us which shared libraries that both /bin/sh and /bin/ls need and copy those into the restricted file system space, too.
Once you have executed the shell, you can expect your new file system with the ls command. On a Debian system, the output looks like this:
sh-3.00# ls -R / /: bin lib /bin: ls sh /lib: ld-linux.so.2 libattr.so.1 libdl.so.2 libpthread.so.0 libacl.so.1 libc.so.6 libncurses.so.5 librt.so.1 |
To run your honeypot in a chroot jail, you need to identify all the files and libraries that it depends on and install them in the restricted filesystem. This can be quite a lot of work, but it potentially limits the damage that an adversary can do to your system because it will be more difficult to read or delete files from elsewhere on the system. In our preceding example, we mentioned ldd to figure out which dynamic libraries an application depends on, but ldd does not tell us which other data files an application like a honeypot relies on. To get this information on Linux, we make use of the strace tool. For example, to figure out which files a tool such as SpyBye, (see Section 8.4.2) relies on, we use the following commands:
$ strace -o /tmp/spybye.output spybye SpyBye 0.2 starting up ... Loaded 90576 signatures Virus scanning enabled Report sharing enabled. [...] |
The strace tool logs all system calls made by SpyBye to the file /tmp/spybye.output. To figure out which other data SpyBye relies on, we just need to look at the output file:
Code View: $ egrep "^(open|access)" | cut -f1 -d'"' | fgrep -v ENOENT | sort -u /etc/host.conf /etc/hosts /etc/ld.so.cache /etc/nsswitch.conf /etc/resolv.conf /lib/libbz2.so.1.0 /lib/libcom_err.so.2 /lib/tls/i686/cmov/libc.so.6 [...] /lib/tls/i686/cmov/libresolv.so.2 spybye.log /tmp/clamav-3000c507821f4c20 [...] /usr/lib/i686/cmov/libcrypto.so.0.9.8 /usr/lib/i686/cmov/libssl.so.0.9.8 [...] /usr/lib/libz.so.1 /usr/local/lib/libevent-1.3b.so.1 /var/lib/clamav/ /var/lib/clamav//daily.cvd /var/lib/clamav//main.cvd |
Based on the output, you know exactly which files to provide in your chroot jail. Of course, the precise output of strace depends on the specific instance of the execution and may not always be the same, but the quintessential files required for running an application should always be there.
Here are some additional words of advice. Never run your low-interaction honeypot as root. The root user has many different ways to break out of the chroot jail. As root, it's also possible that the adversary can kill any other processes running on your system. Ideally, you run your honeypot with a user id that nobody else uses.
Unfortunately, the benefit of chroot is even further diminished by the fact that many Unix systems have vulnerabilities in their system call interface or in their device drivers. If an adversary was able to create device nodes via mknod in the chroot space, it's possible that he could completely break out of it and get full access to your system. We do not consider chroot a comprehensive security solution but rather as raising the bar. Running your honeypots under chroot is going to make an attacker's life somewhat more difficult and is certainly a good safeguard to put in place.
Systrace is an application sandbox available for many Unix systems that restricts an application's access to the system. It was created by one of this book's authors and is being used to protect his honeypot installations.
Systrace limits the access an untrusted application has to your system by enforcing system call policies. This mechanism is called system call interposition, and it means that the sandbox examines the system call and its parameters before allowing it. A good example of a system call is open. The open system call is used to open existing files or create new ones. It takes three parameters: the path, flags that specify if a file should be opened for read or write, and a mode that determines access permissions for newly created files. A policy for the open system call might allow reading files needed for your honeypot and disallow writing files anywhere but a specified log directory.
If you want to use Systrace to sandbox your honeypot, you need to create policies that are specifically tailored toward your honeypot application. Fortunately, Systrace provides a mode in which the policy can be learned interactively. Whenever an application attempts an operation that is not covered by the current policy, Systrace raises an alarm allowing you to refine the configured policy.
For complicated applications, it is difficult to know the correct policy before running them. For that reason, Systrace also supports a mode in which policies can be created automatically based on executing them in a safe environment. The automatically generated policies require some postprocessing but give you a good starting point to work from. Creating reasonable policies usually takes several minutes. Once you have decided on a policy, you can tell Systrace to enforce it. Operations that are not covered by your policy still generate a warning in syslog. Normally, that is an indication of a security problem and might be considered a honeypot mechanism all by itself.
If you are running OpenBSD or NetBSD, your system should already ship with Systrace. You might still want to download the graphical front end for it from http://www.citi.umich.edu/u/provos/systrace/
If you are running Linux, you might be able to find an already precompiled Systrace package or download the source code from the preceding URL.
Here is a quick example of automatically creating a Systrace policy for the ls command. Execute the following command:
$ systrace -A -d /tmp/ ls /tmp/ gsrvdir1000 ssh-lCZYZ22331 test xdvi-c29439
Executing Systrace with the -A option tells it to allow all system calls and to add them to the policy for the application. After ls finishes executing, Systrace writes the resulting policy to /tmp/bin_ls. Let's take a look at it:
Policy: /bin/ls, Emulation: linux linux-newuname: permit linux-brk: permit linux-fsread: filename eq "/etc/ld.so.nohwcap" then permit linux-old_mmap: prot eq "PROT_READ|PROT_WRITE" then permit linux-fsread: filename eq "/etc/ld.so.preload" then permit linux-fsread: filename eq "/etc/ld.so.cache" then permit linux-fstat64: permit linux-old_mmap: prot eq "PROT_READ" then permit linux-close: permit linux-fsread: filename eq "/lib/tls/librt.so.1" then permit linux-read: permit linux-old_mmap: prot eq "PROT_READ|PROT_EXEC" then permit linux-fsread: filename eq "/lib/libacl.so.1" then permit linux-fsread: filename eq "/lib/tls/libc.so.6" then permit linux-fsread: filename eq "/lib/tls/libpthread.so.0" then permit linux-fsread: filename eq "/lib/libattr.so.1" then permit [...] |
In the preceding policy, you see that all operations that the ls command used are logged here. We can make the policy more efficient by using wildcards for some of the operations. For example, we might want to decide that the honeypot should be able to read all files from /lib/. We can replace the corresponding linux-fsread policies with the following line:
linux-fsread: filename match "/lib/*" then permit
Once you have completed the policy, you can execute ls as follows:
$ systrace -a -f /tmp/bin\_ls ls /tmp/ bin\_ls gsrvdir1000 ssh-lCZYZ22331 test xdvi-c29439
Everything works as expected. A good test of the sandbox would be to ask ls to list a directory that is different from /tmp/. As the new directory is not covered by the policy, we would expect that the sandbox will prevent ls from listing its contents. Here is an example:
$ systrace -a -f /tmp/bin\_ls ls /etc/ ls: /etc/: Operation not permitted
As you see, even though ls tried to give you the contents of /etc/, it failed miserably. Furthermore, you should see noticeable warnings about the policy violation in /var/log/messages:
Apr 15 20:15:16 debian systrace: deny user: provos, prog: /bin/ls, pid: 2950(0)[0], policy: /bin/ls, filters: 42, syscall: linux-fsread(195), filename: /etc
Systrace is much more complex than this short example, but you should have an idea of its basic capabilities and how to do simple policy configurations. It is your task now to protect your honeypots with a sandbox. Using Systrace, it is possible to restrict a honeypot's access to your system almost arbitrarily.
If you plan to run larger applications as part of your low-interaction honeypot installation, then protecting them with Systrace is a very good idea. For example, the GHH requires a full-blown web server with a PHP implementation. This makes it a very good candidate for running in a sandbox. The same is true for Honeyd, the low-interaction honeypot framework that we are going to discuss in Chapter 4. If you end up using Systrace, make sure that you monitor syslog carefully for policy violations. Another alternative would be to run your web server or Honeyd in a virtual machine themselves and then treat them as another layer of honeypots. See Chapter 2 for a discussion of high-interaction honeypots.