Previous Page Next Page

2.3. User-Mode Linux

User-Mode Linux is another system you can use to create virtual honeypots. It is very simple to set up, and it is free. However, the main drawback when compared to VMware is the fact that it can only simulate a Linux system. The following sections tell you how to configure and monitor it.

2.3.1. Overview

UML is an architectural port of the Linux kernel to its own system call interface. As a result, the Linux kernel itself can be run as a user process. The actual Linux kernel ("host system") then executes as a process another instance of the Linux kernel ("guest system"). This is similar to the virtual machines that you have learned about in the section on VMware. Each UML instance is a complete virtual machine that is almost indistinguishable from a real computer. This enables an easy way to build a high-interaction honeypot. Similar to VMware, you can use UML to set up a virtual honeypot, and you can benefit from all the advantages a virtual system offers. For example, the host system is not affected by the guest system in terms of configuration or stability. The UML block devices, also called disks, are normally files on the host file system, so you cannot affect the native block devices on which your normal data is stored. One exception is that it is not possible to directly address hardware inside UML. Therefore, devices like network interfaces and hard disks are virtualized. However, the practical implications of this are negligible, and you will not notice the difference.

As the name implies, UML can only run on Linux as an operating system. So if you are running Windows or one of the BSD variants, you cannot use this option to set up a honeypot. In addition, the only option for guest virtual machines is currently Linux. This drawback may seem severe at first sight, but it is not really that bad. In fact, we have learned the most interesting lessons on cyber attacks with compromises of honeypots running Linux. And with UML you have a tool to easily set up many different honeypots running Linux.

As just noted, the UML block devices are normal files on your host system. The guest system uses such a file (normally called root filesystem) as a complete file system, and therefore it is easy to move a UML instance from one machine to another. An interesting option of UML is being able to use a file in copy-on-write (COW) mode. Then the UML instance uses the root filesystem in read-only mode and writes all changes to a separate file: the COW file. This enables you to use one root filesystem that can be used concurrently by several honeypots. On the one hand this saves you some disk space, and on the other hand this allows easier maintenance and administration.

UML is developed by a group of people, the main developer being Jeff Dikes. UML is available for Linux version 2.2.15 or later and all 2.4 and 2.6 versions of the kernel. You can download and access all the UML documentation at http://user-mode-linux.sourceforge.net/. In addition, there is a UML-community site at http://usermodelinux.org. If you have any problems using UML, you can also join the IRC channel #uml on irc.usermodelinux.org and ask questions there.

2.3.2. Installation and Setup

After a brief overview of UML, we are now going to explain the process of installing and setting up a virtual high-interaction honeypot based on UML. The host and guest system will be Linux, and our distribution for the honeypot is Red Hat Linux 9. This Linux distribution has by default several vulnerable services and allows an attacker to compromise the honeypot without too much effort. We can then study his modus operandi while observing what he is doing on the compromised system.

All major Linux distributions have support for UML. Therefore, installing UML is straightforward if you want to use the package management from your Linux distribution of choice. For example, if you run Debian, you can install UML with the following command:

$ sudo aptitude install user-mode-linux user-mode-linux-doc uml-utilities

The package user-mode-linux contains the kernel itself as an executable program and all the kernel modules needed to run UML. With the package user-mode-linux-doc, some additional documentation is installed. You can use it for reference, and it is located at /usr/share/doc/user-mode-linux-doc/. Finally, the package uml-utilities contains several programs that can be used in combination with UML. For example, the program uml_switch can be used to manage a virtual network between several UML systems, with no connection to the host system's network. We will introduce all utility programs and explain their usage later on.

When using Fedora Core, the proceeding is similar. With the command

$ sudo yum install kernel-uml kernel-uml-modules

you can install UML on your machine. Please consult the documentation of the distribution you are using if you are not running Debian or Fedora Core. For example, if you run Gentoo Linux, you find the documentation at http://www.gentoo.org/doc/en/uml.xml.

Of course, you can also install UML by hand. This is necessary if you want to customize it to your needs or if your Linux distribution does not offer this package. Please notice that the installation process requires you to build a new Linux kernel, which you do not need if you install a package. Therefore, you should have some experience with Linux and be aware of the caveats involved. In the following, we give step-by-step installation help that aids you in the process of installing UML. As just noted, UML runs on all kernels after Linux 2.2.15. We describe both the process of installing UML on Linux 2.4 and Linux 2.6. The process of installing UML for Linux 2.2.15 and later is similar to the one for Linux 2.4; only the paths and version numbers have to be adjusted.

If you want to install UML in a version for the 2.4 series of Linux, you need to patch the kernel itself to build it. In this example, we have chosen Linux version 2.4.20. This rather old Linux version has several vulnerabilities that allow an attacker to locally escalate his privileges. This enables us to learn more about the proceedings of the attacker, since we allow him full access to the system. Patching is not necessary for Linux 2.6 because UML is already included.

The installation process is straightforward. We install UML in the directory uml-honeypot in your home directory. At first, please make sure that you have all dependencies installed. Since you need to compile the Linux kernel, you need a full developer environment and the corresponding sources of the Linux kernel. These are available via the Linux Kernel Archives at http://kernel.org/ or one of the mirrors (http://kernel.org/mirrors/. Download version 2.4.20 (http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.20.tar.bz2) to your local disk and unpack the package:

$ mkdir ~/uml-honeypot
$ cd ~/uml-honeypot
$ curl -O http//www.kernel.org/pub/linux/kernel/v2.4/linux-
 2.4.20.tar.bz2
$ tar xjvf linux-2.4.20.tar.bz2


As a result, you should now have a directory linux-2.4.20 that contains the sources of the Linux kernel. You also need all the necessary tools to compile the kernel, such as the GNU Compiler Collection (GCC) and GNU Make. A complete enumeration and the minimum software versions for a kernel build can be found in the file linux-2.4.20/Documentation/Changes.

In the second step, you need to apply the UML patch to the kernel sources to be able to build it. You can download the patch at the website of UML at http://user-mode-linux.sourceforge.net/dl-2.4-patches-sf.html. To continue the example, download the UML patch in version uml-patch-2.4.20-8.bz2, the latest version for Linux 2.4.20. Afterward, apply the patch to the kernel source. The following commands conduct this:

$ cd ~/uml-honeypot
$ curl -O http//superb.dl.sourceforge.net/sourceforge/user-
  mode-linux/uml-patch-2.4.20-8.bz2
$ bunzip2 uml-patch-2.4.20-8.bz2
$ cd linux-2.4.20/
$ patch -p1 < ../uml-patch-2.4.20-8


The command patch will carry out the actual patching of the original Linux kernel. You should see many status messages of the form:

patching file arch/um/common.ld.in
patching file arch/um/config\_block.in
patching file arch/um/config\_char.in
patching file arch/um/config.in
[...]


After this command has succeeded, it is time to compile the kernel. This is also the case if you are using a 2.6 version of Linux, since it already includes support for UML. We first have to configure the kernel and then actually build it. In the running example, we use the ncurses-based front end to configure the kernel source. To be able to use this front end, please make sure that the ncursesdevel libraries are installed. If you prefer another front end, you can substitute it within the example. For example, to obtain a graphical, X Window-based front end, use make xconfig. Please make sure that the configuration process targets the desired architecture — in our case UML:

$ make ARCH=um menuconfig

Within the ncurses-based front end, you can navigate with the help of the cursor up and down keys. You can select items with the Enter key and the Tab key changes the focus. Press the highlighted letter on each option to jump directly to that option. If you want to add an option to the kernel, press Y to add it directly into the kernel. If applicable, you can also press M to add it into the kernel as a module. Press N if you want to disable an option. Each item has also a help menu, which you can access by either pressing Enter when the "Help" item is highlighted or by pressing?

In the likely event that you do not want to change anything, just exit the configuration front end and save the new kernel configuration. You can also change parameters: Configure the UML kernel as you would configure a normal Linux kernel. For more information about the configuration process, consult either the documentation of your Linux distribution or the Kernel Rebuild Guide (http://www.digitalhermit.com/linux/Kernel-Build-HOWTO.html). Afterward, the actual compilation process can begin. As a target, we choose to build a UML kernel:

$ make ARCH=um linux

The compilation process will take some time, and afterward you should obtain a binary linux in the directory linux-2.4.20. This is the executable Linux kernel that we use to build a UML-based honeypot. As you may notice, this binary file is pretty large. This is due to the fact that it also includes information useful for debugging purposes. Since we do not need this information within the binary, we can save some disk space by removing this data:

$ strip linux

Besides the actual kernel, we also need to build the corresponding modules:

$ make ARCH=um modules

Again, this process can take some time, depending on the number of modules and the speed of your computer. Later on, we will copy the resulting modules to the virtual UML machine to be able to actually use them. There is another way to copy the modules to the UML system, provided that the root filesystem is not a COW filesystem.

If the UML kernel is not booted, you can mount the root filesystem root-fs on the host system and then install all modules:

$ mount -o loop /path/to/root-fs /mnt
$ make modules_install INSTALL_MOD_PATH=/mnt ARCH=um
$ umount /mnt


At this point, the manual installation process is finished, and we have all the necessary prerequisites to start with a virtual high-interaction honeypot running on UML.

2.3.3. Runtime Flags and Configuration

To run UML, we need a disk image besides the UML kernel itself: the root filesystem. You can either build one on your own or use one of the preconfigured filesystems available at the UML website. Building our own root filesystem is outside of the scope of this book, so we will use one of the preconfigured filesystems. Once you are familiar with the process of building a honeypot with UML, you can also experiment with your own filesystems and virtual machines.

We can download a root filesystem at http://user-mode-linux.sourceforge.net/dl-sf.html. To build a honeypot that is likely to be compromised fairly soon, we choose root_fs.rh-9-full.pristine.20030724.bz2 and download the file. This system is based on Red Hat 9 and has by default several vulnerable services, so the chances are high that an adversary will successfully compromise our virtual honeypot. After the download has finished, we extract the root filesystem and boot a basic UML system:

$ bunzip2 root_fs.rh-9-full.pristine.20030724.bz2
$ mv root_fs.rh-9-full.pristine.20030724 root_fs.rh-9
$ linux ubd0=root_fs.rh-9 devfs=mount eth0=tuntap,tap0,,192.168.1.2


The parameter ubd0=root_fs.rh-9 tells UML to use the disk image root_fs.rh-9 as root filesystem on usermode block device 0, the virtual disk drive. With the eth0 parameter, we configure a virtual network interface. We describe the whole process involved in virtual networking later. For now it is only necessary to know that we set up a network similar to NAT networking with VMware.

Optionally, you can also configure a swap partition that the guest system can use. To create a 256MB swap file, use the following commands and append the parameter ubd1=swap-fs to the preceding command line.

$ dd if=/dev/zero of=swap-fs count=256 size=1024k
$ /sbin/mkswap swapfs

The UML system will start up, and the following log messages should appear:

Checking for the skas3 patch in the host\ldots not found
Checking for /proc/mm\ldots not found
tracing thread pid = 25446
[...]


Now you have booted a full Linux Red Hat 9 system as a guest virtual machine and you see the normal login prompt. You can log in to this machine with the user-name root and password root. At first, you should change the password with the help of the command passwd. Now you can interact with your virtual machine as you would with a normal Linux installation. The process is (almost) completely transparent, and you should see no obvious signs that you are within a UML system. We introduce several ways to detect a UML system in Chapter 9 and also present best practice recommendations to harden a UML system in that chapter.

With UML it is also possible to set up a virtual network. Our choices are not as sophisticated as with VMware, but nevertheless we have some flexibility. Figure 2.4 depicts an overview of the virtual network that we use in this example. As a prerequisite, please make sure that the host system has masquerading and TUN/TAP support compiled into the kernel. You can check this with the command sudo modprobe tuntap && sudo modprobe iptable_nat as the root user. If the command returns with an error message, please consult the documentation of your Linux distribution on how to enable the support. To configure the network on the host computer, we need to execute the following commands:

## Configuration of virtual network at host system
##
# Load all necessary kernel modules
# Enable the virtual network device
/sbin/modprobe tun
/sbin/modprobe netlink_dev
/usr/sbin/tunctl -u username

# Enable IP forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/conf/tap0/proxy_arp

# Assign an IP address to the virtual device
/sbin/ifconfig tap0 192.168.1.2 up

# Use the IP address from the UML system here
/sbin/route add -host 192.168.1.3 dev tap0
/usr/sbin/arp -Ds 192.168.1.3 eth0 pub

# Enable masquerading
/sbin/iptables -A FORWARD -i tap0 -o eth0 -m state
           --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A FORWARD -i eth0 -o tap0 -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE


Figure 2.4. Virtual network for UML-based virtual honeypot.


The first commands configure a TUN/TAP device on the host system. This is a virtual network device used for tunneling packets between UML and the host system. Please make sure that you substitute username with the actual username that is running UML. With the help of ifconfig, we assign an IP address to the tap0 interface and afterward enable IP forwarding and proxy ARP in order to correctly handle network traffic on that interface.

With the help of the netfilter/iptables subsystem of the Linux kernel, we enable the routing between the tap0 network interface of the UML instance and the eth0 network interface of the host machine. We forward all packets between the two systems and also enable NAT so that the host system acts as a gateway for the virtual machines and correctly forwards and translates the packets coming from the virtual machine.

Once we have finished the configuration of the host system, we must also configure the virtual network of the guest system. As the IP address of the first network interface eth0, we use the one for which we configured Proxy ARP during the configuration phase of the host system. We configure the default gateway as the IP address we assigned to the tap0 virtual device. Afterward, everything should be ready, and we can try with the help of the tool ping to reach other hosts within the network.

## Configuration of virtual network at guest system
##
# Configure eth0 with correct IP address and add routing
/sbin/ifconfig eth0 192.168.1.3 up
/sbin/route add default gw 192.168.1.2

# Try if everything worked

# Try to ping public IP address of host system
/bin/ping -c 3 192.168.1.2

# Try to ping external IP address, e.g., honeyblog.org
/bin/ping -c 3 85.214.26.53

# Test whether DNS resolution works, e.g., honeyblog.org
/bin/ping -c 3 honeyblog.org


The network is now up and running, and therefore the configuration phase of our honeypot is almost completed. Please be aware that we have configured the virtual network as a NAT network. Your honeypot is not reachable by other machines from the Internet, so it is currently in a testing phase. In a later section we explain how to change the configuration so that the virtual honeypot uses a real IP address.

You can configure all the different services offered by the default Red Hat 9 installation to your personal preferences. In addition, you can install additional services if you like. Then your honeypot is finished already and you can experiment with this setup.

There are also four utility programs that help in dealing with UML:

2.3.4. Monitoring UML-Based Honeypots

Like to VMware-based honeypots, we also need to set up some additional tools to monitor our UML-based honeypots. Primarily you will be interested in network logs, since you get detailed information about the attacker this way. If you use tcpdump or Wireshark/Tshark on the tap0 interface, you will monitor all traffic entering and leaving the honeypot. In addition, you may want to install an IDS system on the host system to get more detailed information about malicious network activities.

On the guest virtual machines, UML offers an interesting possibility that is not that easy to implement with a physical honeypot. It is possible to log all traffic passed through tty devices — that is, UML terminals — to the host system in a transparent way. To enable this mechanism, you have to enable an option before the compilation process. Set the variable CONFIG_TTY_LOG, which can be found under Character Devices, Enable tty logging. After the compilation process, your UML instance will log all terminal sessions to the host system. By default, these logs will be stored in different files within the current directory, but you can change this with the help of the command line option tty_log_dir=<directory>. For each tty session, a logfile will be created. A session is defined as all data that is captured between opening and closing a UML terminal. This can be quite a lot of different files, and you may want to log everything in just one single file. To do so, use the command line parameter tty_log_fd=3 3> tty_log_file to set the log stream to a separate file descriptor and then redirect this file descriptor to a file. The resulting logfile has the following structure:

struct tty_log_buf {
      int what; // action, see below
      unsigned long tty;// unique identifier of the tty device
            int len;// how much data follows the record
      int direction; // TTY_READ or TTY_WRITE
      unsigned long sec; // timestamp
      unsigned long usec; // timestamp
};

with 'what' having the possible values

#define TTY_LOG_OPEN 1
#define TTY_LOG_CLOSE 2
#define TTY_LOG_WRITE 3


The resulting logfile can be examined with some tools available at http://www.user-mode-linux.org/cvs/tools/ (jail/tty_log.pl or jail/playlog.pl). tty_log.pl is a rather simple script that just parses the logfiles and prints them to your terminal. In contrast to this, playlog.pl is more comfortable. It replays the session with tty output and original timing so that you can see what the attacker typed. Use it with

$ /usr/bin/perl playlog.pl [-f] [-n] [-a] <tty_log_file> [tty-id]

with tty-id being the session you want to view. With the -f option, you get a "live" log similar to tail -f. The -n option dumps the session instead of following the original timing. Finally, you can use -a to display all data and not only tty output. This is handy to see also passwords or other data that is normally not echoed back to the terminal.

More information about the tty logging possibilities can be found at http://user-mode-linux.sourceforge.net/tty_logging.html.

2.3.5. Connecting the Virtual Honeypot to the Internet

The virtual network interface of the virtual honeypot has up to now a private IP address. Hence, it is not reachable by other machines from the Internet. You can use such a NAT networking setup to test the functionality of your honeypot and to make yourself familiar with UML. However, if you want to learn more about cyber attacks, you need to configure the virtual network adapter so that it has a real IP address.

At first, make sure that you have a second IP address you can use for the virtual system. Either your ISP can provide you with one, or if you are setting up the honeypot within a corporate environment, consult your network administrator. You should read Section 2.5 carefully to learn how to safeguard your honeypot. You must know which risks are involved when running a honeypot and how to mitigate the risks.

With the following commands, you configure the network interfaces at the host system to correctly route all packets to the guest virtual machine:

## Configuration of virtual network at host system
##
# Load all necessary kernel modules
/sbin/modprobe tun
/sbin/modprobe netlink_dev

# Enable IP forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/conf/tap0/proxy_arp

# Use the IP address from the UML system here/usr/sbin/arp -Ds <public IP of guest> eth0 pub

# Enable masquerading
/sbin/iptables -A FORWARD -i tap0 -o eth0 -m state
           --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A FORWARD -i eth0 -o tap0 -j ACCEPT
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

					  


Then boot up the guest virtual machine with the command line

$ linux ubd0=root_fs.rh-9 devfs=mount eth0=tuntap,,,<public IP of host>

and configure the network device eth0 of the guest system with the correct IP address. Make sure that the network is working correctly and that you can reach other systems on the Internet from the honeypot. Moreover, test whether other systems on the Internet can reach your honeypot. Now your honeypot is up and running. It collects information about malicious network traffic, and by an analysis of the collected data, you can learn more about the tools, tactics, and motives of attackers.

2.3.6. Building a Virtual High-Interaction Honeynet

Up to now, we have set up a virtual high-interaction honeypot running in UML. Of course, you can also build a high-interaction honeynet. This is even easier with UML than with VMware. We just have to start a new UML instance and configure the virtual network interface accordingly. The steps are very similar to the ones outlined in the previous sections. You just have to substitute the appropriate IP addresses and configure the correct path.

The copy-on-write (COW) capability allows several UML instances to share one root filesystem. Each UML instance uses the root filesystem in read-only mode and stores the changes in an additional file. This helps you to save some disk space and makes the configuration process easier, since you need to change only one filesystem, and all UML instances will benefit from it. Then you can set up several honeypots and connect them via the virtual network, and you have your virtual honeynet!

Previous Page Next Page