Tribal Chicken

Security. Malware Research. Digital Forensics.

Guide: Cuckoo Sandbox on FreeBSD

This is a guide through configuring a basic Cuckoo Sandbox installation on a FreeBSD host. The main points of difference between a Linux and a FreeBSD install lie in the configuration of the firewall for the host to NAT connections between the Virtualbox host-only network and the Internet.

I don't often write guides, however decided to note down my experiences in the hope that it will save others some work. Having said that, it's not a complete step-by-step walkthrough describing how to go from zero to cuckoo, but explains the FreeBSD-specific steps - The rest can be achieved by following the official Cuckoo documentation.

Installation of prerequisites

According to the documentation, cuckoo has a few main dependencies:

  • Python, and some additional Python libraries
  • Hypervisor (the default is Virtualbox)
  • Software firewall for routing

The only option for installing Virtualbox on FreeBSD is the Open Source Edition (OSE) which does not include some features, however it is more than sufficient for use with Cuckoo. There are a couple of pre-packaged options for virtualbox (OSE) so you do not need to build from source - virtualbox-ose and virtualbox-ose-lite. The latter is good for headless installs as it doesn't carry all the dependencies of a GUI install.

The rest of the Python dependencies are in the FreeBSD repositories. In this case I am using pkg, but you could also install from Ports if you prefer. The equivalent packages to install on FreeBSD are:

#> pkg install python27 libffi py27-openssl py27-libxml2 py27-libxslt jpeg py27-yara py27-pydeep tcpdump py27-pip

Optionally, if you plan to use the build in web-interface, you can install MongoDB as well:

#> pkg install mongodb 
tcpdump

In order for Cuckoo to capture traffic you will need to setuid the tcpdump binary. Keep in mind the security/privacy caveats of setting the setuid bit on tcpdump in multiuser environments (I.E. Any shell user on the system can use tcpdump to sniff all traffic). Ideally though, your Cuckoo host will not be a multiuser system.

#> chmod +s /usr/sbin/tcpdump

If you do not setuid you may see warnings similar to the one below in your Cuckoo log file:

[lib.cuckoo.core.plugins] WARNING: Unable to stop auxiliary module: Error running tcpdump to sniff the network traffic during the analysis; stdout = '' and stderr = "tcpdump: vboxnet0: You don't have permission to capture on that device\n((cannot open device) /dev/bpf: Permission denied)\n". Did you enable the extra capabilities to allow running tcpdump as non-root user and disable AppArmor properly (only applies to Ubuntu)?

When you have the latest Cuckoo package downloaded, don't forget to use pip to install the rest of the dependencies:

pip install -r requirements.txt  

Virtualbox host-only network

Once Virtualbox is installed you would want to set it to start the host-only network on boot, by editing /etc/rc.conf to include:

vboxnet_enable="YES"  

At this point you may also need to create the host-only network vboxnet0::

#> VBoxManage hostonlyif create
#> VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.56.1

On that note, we can move on to the largest section of this guide - configuring networking on your FreeBSD host. Before doing so however, just check the Cuckoo Documentation to see if there are any intermediate steps.

Cuckoo Configuration

Cuckoo itself is platform-independent and requires no special configuration to work properly on FreeBSD. Simply follow the Cuckoo Documentation
to get it configured.

Networking

The sandbox machines will generally need an internet connection, and here we assume (as the documentation does) that traffic from the sandboxes will be routed out through the connection of the host. You may prefer a different solution (E.G. routing through a VPN), and if so you can still be able to adapt this to suit.

The Cuckoo documentation includes sample Linux firewall rules to forward the traffic from the sandbox machines to the outside world. In order to enable Internet access on a FreeBSD host we need to adapt these rules. FreeBSD ships with two software firewalls / packet filters - pf and IPFW. You can choose your poison, depending on which you prefer.

The configuration of NAT for both PF and IPFW have been derived from their respective pages in the FreeBSD Handbook and are based on their default policies of default-allow and default-block, respectively.

Note: Ultimately you are responsible for ensuring your firewall rules are adequate for your environment. Remember you are dealing with live malware here - running your Cuckoo host on your internal LAN is probably a bad idea regardless of how well configured your firewall is!

PF

If you do not already have a PF setup then you can either create an empty /etc/pf.conf, or copy from /usr/share/examples/pf. If you do already have a working configuration then you would look to adapt this to your existing ruleset.

Configuring PF rules to NAT the connection is actually rather simple. The default policy is permissive, so for a very basic NAT we simply need one rule:

# Where hn0 is your Internet-facing interface
nat on hn0 from (vboxnet0:network) to any -> (hn0)  

Note that this will allow the Cuckoo VMs access to any network reachable from the interface hn0. You may need something a little more complex (or change to default-block). Consider the following, which uses a table to disallow access to private (RFC1918) networks with the exception of the main gateway sitting on 192.168.0.254 and the host-only interface of 192.168.56.1. This effectively only allows access to the Internet, and is an example from testing on my 'untrusted' network.

table <private> const { 10/8, 172.16/12, 192.168/16, !192.168.0.254, !192.168.56.1 }  
nat on hn0 from (vboxnet0:network) to !<private> -> (hn0)  

If you do not already have PF enabled, you will need to enable it in /etc/rc.conf as well as enabling LAN gateway forwarding (which takes care of setting net.inet.ip.forwarding=1) with:

pf_enable="YES"  
gateway_enable="YES"  

Finally:

#> service pf start

This should allow NAT from the VirtualBox host-only network to the outside world.

IPFW

IPFW requires a slightly more complex ruleset to establish basic NAT, if you keep the default-block policy.

This is once again based almost exclusively on the FreeBSD Handbook (though is a bit more lenient) and establishes some rules to divert traffic through natd.

Below is an IPFW script to be placed into /etc/ipfw.rules - You can use variables to simplify configuration and maintenance, however I've left variables out in this example to make it easier to follow. Once again, if you have existing IPFW rules you could integrate this into your existing ruleset.

# Host-only network: vboxnet0
# External-facing network: hn0
# Network attached to hn0 (You may wish to tweak this): 192.168.0.0/24

ipfw -q -f flush

ipfw -q add 00005 allow ip from any to any via vboxnet0  
ipfw -q add 00006 allow ip from 192.168.0.0/24 to any via hn0  
ipfw -q add 00010 allow ip from any to any via lo0  
ipfw -q add 00100 divert natd ip from any to any in via hn0  
ipfw -q add 00101 check-state  
ipfw -q add 00121 skipto 500 udp from any to any out via hn0 keep-state  
ipfw -q add 00125 skipto 500 tcp from any to any out via hn0 keep-state  
ipfw -q add 00130 skipto 500 log icmp from any to any out via hn0 keep-state  
ipfw -q add 00499 deny ip from any to any  
ipfw -q add 00500 divert natd ip from any to any out via hn0  
ipfw -q add 00510 allow ip from any to any

Of course this will need some configuration in /etc/rc.conf as well, to enable both the NAT daemon and the firewall and load the above script.

natd_enable="YES"  
natd_interface="hn0"  
natd_flags="-dynamic -m"  
firewall_enable="YES"  
firewall_script="/etc/ipfw.rules"  

Finally:

#> service natd start
#> service ipfw start

Using either option should get you a basic NAT configuration which will allow Internet access from the host-only network vboxnet0 via the host's Internet connected interface. You will most likely need a more complex ruleset, depending on your host configuration and how it is connected to the Internet - don't forget that live malware will be bouncing around in there.

VM Build

You can go ahead and build your VM's now as per the documentation. I suggest using vmcloak, which is rather good, although at the time of writing the documentation appears to be out of date which means you may need to dig around to find the right options for your environment. The only FreeBSD-specific configuration required for vmcloak is the method in which you would mount the ISO files of the desired Windows version. Windows XP works fine through a standard mdconfig & mount:

#> mdconfig -a -t vnode -f WINXP.ISO
# Note down the number following /dev/md
#> mount -t cd9660 /dev/mdX /mnt/winxp

However, mount_udf seems to struggle with the UDF format of Windows 7 ISO. Whilst perhaps not the most elegant solution, it may be simpler to use p7zip to extract the contents of the ISO:

#> pkg install p7zip #If not already installed
#> 7z x Win732bit.iso -o /mnt/win7/
#> chmod 744 /mnt/win7 

If you are not using vmcloak, then simply build the sandbox machines as per the Cuckoo documentation.

Conclusion

From this point there is nothing special required to run Cuckoo on FreeBSD, you can simply continue as per the Cuckoo Documentation to register your virtual machines, start Cuckoo and submit some samples.

Feedback is most welcome. Happy malware hunting!