Cuckoo Sandbox Setup for People in a Hurry

Blog.

Introduction

This blog post aims to provide a straightforward install for Cuckoo that is easy to follow, using as much of the built-in automation as possible.

The first part of the guide will be setting up a basic install that should be sufficient for a single-user setup with a low number of machines.

For people who want to run Cuckoo on more resources, or run a production web interface for multiple people, some different dependencies have to be used. When using parallel results processing and multiple VMs, SQLite should be replaced with a DBMS such as Postgres, which handles multiple processes more reliably. The development web server can be replaced with uWSGI + nginx. This is discussed in the Cuckoo Web Interface section of this blog post.

This setup guide is tested to work on a clean install of Ubuntu 18.04 LTS, on other distros your mileage may vary.

We will install VirtualBox, set up a virtualenv for Python and create a low-privilege user for cuckoo. Then create the analysis VMs using VMCloak to automatically install Windows 7, software, and to create snapshots, after which we will use the built-in ‘cuckoo machine’ command to add them to the configuration.

First of all, let’s get our package manager up-to-date, install virtualenv, and make sure we have the right core tools installed:

sudo apt-get update
sudo apt-get -y install python virtualenv python-pip python-dev build-essential

Secondly, we will create a new user to run Cuckoo under. Running Cuckoo under a separate user is important for a safe setup, we’re dealing with malware; if a vulnerability is found and exploited it will be harder to compromise the whole machine from a low-privileged user:

sudo adduser --disabled-password --gecos "" cuckoo

The user should be able to create network dumps during Cuckoo analyses, so we give it permission to do so:

sudo groupadd pcap
sudo usermod -a -G pcap cuckoo
sudo chgrp pcap /usr/sbin/tcpdump
sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump

One more step before we start, we need a Windows 7 ISO. Let’s download one that we found and know that it works. After downloading, we have to mount the ISO to be used at a later step:

wget https://cuckoo.sh/win7ultimate.iso
mkdir /mnt/win7
sudo mount -o ro,loop win7ultimate.iso /mnt/win7

Installing VirtualBox

We will install VirtualBox from the VirtualBox repository, as this allows for easier upgrading to newer releases. It is important to install updates for the virtualization layer, as they might include security updates. Especially for VirtualBox, which has seen numerous 0day vulnerabilities in the last years, it’s important to run the latest version of VirtualBox 5 or VirtualBox 6 (at the time of writing, this would be either 5.2.30 or 6.0.8).

First, we add the repository keys:

wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add -
wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add -

Adding the VirtualBox repository:

sudo add-apt-repository "deb [arch=amd64] http://download.virtualbox.org/virtualbox/debian $(lsb_release -cs) contrib"

Let’s update the package list and download VirtualBox. Doing so will allow us to install the latest version of VirtualBox 5.2 or 6.0, whichever is preferable. After the installation, we add the cuckoo user to the vboxusers group:

sudo apt-get update
sudo apt-get install virtualbox-5.2
sudo usermod -a -G vboxusers cuckoo

Or for VirtualBox 6.0:

sudo apt-get update
sudo apt-get install virtualbox-6.0
sudo usermod -a -G vboxusers cuckoo

Cuckoo and VMCloak installation

Before we install Cuckoo and VMCloak, the installation of multiple packages is required. These are dependencies VMCloak or Cuckoo require to function.

VMCloak and Cuckoo required packages:

sudo apt-get -y install build-essential libssl-dev libffi-dev python-dev genisoimage
sudo apt-get -y install zlib1g-dev libjpeg-dev
sudo apt-get -y install python-pip python-virtualenv python-setuptools swig

Now that the dependencies have been installed, we can install Cuckoo and VMCloak. Start by switching to the cuckoo user and creating a new virtualenv:

sudo su cuckoo
virtualenv ~/cuckoo
. ~/cuckoo/bin/activate

The virtualenv will allow us to install dependencies within our home directory and to prevent interference with other, globally installed, Python packages.

Install both VMCloak and Cuckoo Sandbox within the same virtualenv:

pip install -U cuckoo vmcloak

Automatic VM creation

Manually installing Windows, required software, editing registry keys, etc is a lot of work. Luckily, we don’t have to do that because we will use VMCloak!

First, start by defining and instantiating a VirtualBox Host-Only network adapter for the VMs to use:

vmcloak-vboxnet0

To set up a Windows VM, we will use the ISO that we mounted earlier. VMCloak will try /mnt/win7 (and /mnt/win7x64) by default. The following step will create the VM and automatically install Windows. This step will take approximately 15 to 20 minutes. A Cuckoo analysis VM should have at least 2GB of memory and preferably two or more CPU cores.

The syntax of the command we will use is: vmcloak init <os flag> <vmname> <options>:

vmcloak init --verbose --win7x64 win7x64base --cpus 2 --ramsize 2048

After VMCloak is finished we can start installing software that should be present in VM snapshots. When we have created snapshots of an image, it can no longer be changed, therefore we clone the cleanly installed base image so we can install software on the clone and snapshot that:

vmcloak clone win7x64base win7x64cuckoo

VMCloak supports the installation of multiple software packages. A full list of supported packages and versions can be listed:

vmcloak list deps

A software package can be installed with the following syntax: vmcloak install <image name> <package>. A specific version or a serialkey can be provided by adding: package.version=X or package.serialkey=X. If no version is selected, the default version will be picked. We will be installing some basic software packages:

vmcloak install win7x64cuckoo adobepdf pillow dotnet java flash vcredist vcredist.version=2015u3 wallpaper

Optional step: installing Internet Explorer 11:

vmcloak install win7x64cuckoo ie11

Optional step: Installing a Microsoft Office version so that Office document can be analyzed. Office 2007 is most likely to work, some builds of higher versions of Office sometimes cause issues with the Cuckoo Monitor:

vmcloak install win7x64cuckoo office office.version=2007 office.isopath=/path/to/office2007.iso office.serialkey=XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

When finished with installing software packages, we can create the VM snapshots. VMCloak will register a VirtualBox VM for each snapshot created. After snapshotting, it is no longer possible to change the image. The syntax of the snapshot command is: vmcloak snapshot <options> <image name> <vmname> <ip to use>

Using the --count parameter, we can create multiple snapshots at once. Let’s create four:

vmcloak snapshot --count 4 win7x64cuckoo 192.168.56.101

This command will create VMs win7x64cuckoo1-4 with IPs 192.168.56.101-104.

After VMCloak is finished, the VMs can be listed using:

vmcloak list vms

Configuring Cuckoo

Cuckoo loads its configuration files, signatures, and other user-changeable files from its Cuckoo Working Directory (CWD). By default this will be $USERHOME/.cuckoo. Before we can use Cuckoo, we first have to create this directory:

cuckoo init

If a custom CWD is desired, the --cwd <path> option must be used upon creation and must be supplied when using Cuckoo commands, e.g.:

cuckoo --cwd /tmp/cuckoo init

Postgres as DBMS

You can skip this section and jump to [Adding VMs][Adding VMs] if you are not using more than a couple of analysis VMs and will not be using Cuckoo processing instances.

First, start by installing Postgres if it is not already installed:

sudo apt-get postgresql postgresql-contrib

Then we install the Postgres database driver for Cuckoo:

pip install psycopg2

Now let’s create a user and database for Cuckoo to use:

sudo -u postgres psql
CREATE DATABASE cuckoo;
CREATE USER cuckoo WITH ENCRYPTED PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE cuckoo TO cuckoo;
\q

After that, we have to tell Cuckoo to use Postgres instead of SQLite. Open the $CWD/conf/cuckoo.conf file and find the [database] section. Change the connection = line to:

connection = postgresql://cuckoo:password@localhost/cuckoo

Adding VMs

We are using VirtualBox in our setup, this is the default Machinery module that Cuckoo uses. We have to remove some default settings from its configuration file virtualbox.conf.

All Cuckoo configuration files can be found at $CWD/conf/. Open $CWD/conf/virtualbox.conf and remove the entries in the machines = cuckoo1 line.

Time to add the created VMs to Cuckoo. We will use the cuckoo machine --add <vm name> <ip> to tell Cuckoo to add the machine to its configuration. This has to be done for each machine, so let’s make life easier and use vmcloak list vms:

while read -r vm ip; do cuckoo machine --add $vm $ip; done < <(vmcloak list vms)

To install the Cuckoo signatures and latest monitor, we run the following command:

cuckoo community --force

Network configuration

Next, providing analysis VMs with an internet connection.

Internet on the VMs is not required, however, not having an internet connection restricts malware from retrieving data such payloads and instructions. This can affect the accuracy of the analysis results.

Configuring traffic forwarding can be done globally or on a per-analysis basis. The latter requires more steps, so we will start with the global forwarding rules.

First, switch to an account that has root privileges and enable forwarding. Do this for the vboxnet0 interface and the outgoing interface. We will be using eth0 as a dummy value here. Replace it with your outgoing interface (which can be identified through, e.g., ifconfig):

sudo sysctl -w net.ipv4.conf.vboxnet0.forwarding=1
sudo sysctl -w net.ipv4.conf.eth0.forwarding=1

Global forwarding rules

To enable global routing for all VMs connected to the vboxnet0 interface, use the following rules:

sudo iptables -t nat -A POSTROUTING -o eth0 -s 192.168.56.0/24 -j MASQUERADE
sudo iptables -P FORWARD DROP
sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -s 192.168.56.0/24 -j ACCEPT

Per-analysis routing - Advanced

Cuckoo allows for multiple types of per-analysis routes, among which are ‘internet’ and ’none’. The route can be specified whens submitting an analysis.

To accomplish per-analysis routing, Cuckoo uses the Cuckoo Rooter. This is a separate process that runs with root privileges and is able to execute pre-defined commands.

We start by creating a Cuckoo Rooter process. This creates a UNIX socket owned by root and giving the ‘cuckoo’ group permission to use it. Do not run these commands with sudo. The --sudo flag will take care of this:

cuckoo rooter --sudo --group cuckoo

Since Cuckoo is installed in a virtualenv, and the Cuckoo user should not have root privileges, we can do the following from a root privileged user:

/home/cuckoo/cuckoo/bin/cuckoo rooter --sudo --group cuckoo

Next, we have to edit $CWD/conf/routing.conf to tell Cuckoo what our outgoing interface is. Open routing.conf and change internet = none to internet = eth0.

This config file also contains a route = none line. This is the default routing it will use. This can be changed to internet to give each analysis internet access, unless a different routing option is provided upon sample submission. A command line submission example: cuckoo submit <file path> --options "route=internet".

Note: if the routing configuration is changed to support per-analysis routing, Cuckoo requires the Cuckoo Rooter to be running and will not start otherwise.

The Cuckoo Web Interface

The Cuckoo web interface can be used to submit new tasks and view analysis results. It requires MongoDB to be installed and enabled in the reporting.conf.

If MongoDB is not installed, start by installing it:

sudo apt-get install mongodb

The web interface can be used by starting the built-in development server or by configuring a uWSGI + NGINX setup for a production environment.

Results will only show if they have been processed after MongoDB has been enabled. As Cuckoo will not store them in there by default.

We start by opening $CWD/conf/reporting.conf and find the [MongoDB] section. Change enabled = no to enabled = yes. No further configuration changes are required, unless your MongoDB setup requires a user, runs on a non-standard port, or runs remotely.

The built-in web server

This server should not be used for production environments. It is a development server. It can be used for small setups, but should not be exposed to the internet.

The server can be started by running:

cuckoo web --host 127.0.0.1 --port 8080

We can now submit tasks and view results in the web interface. Cuckoo must be running for analyses to start, otherwise tasks will remain on the pending status.

Using uWSGI and nginx - Advanced

Cuckoo web can be set up to be served by nginx. This greatly increases the maximum amount of users a Cuckoo web interface can have at one time, and allows for the usage of TLS.

To run Cuckoo web with uWSGI, we must first install the uwsgi Python dependency in the virtualenv where we installed Cuckoo:

pip install uwsgi

After this, ensure the following packages are installed:

sudo apt-get install uwsgi uwsgi-plugin-python nginx

Cuckoo can generate the configurating files for uWSGI and nginx. First, let’s set up uWSGI:

cuckoo web --uwsgi > cuckoo-web.ini
sudo cp cuckoo-web.ini /etc/uwsgi/apps-available/cuckoo-web.ini
sudo ln -s /etc/uwsgi/apps-available/cuckoo-web.ini /etc/uwsgi/apps-enabled/cuckoo-web.ini

Ensure that the www-data user can read the Cuckoo web files by adding it to the cuckoo group:

sudo adduser www-data cuckoo
sudo systemctl restart uwsgi

Second, let’s set up nginx. The generated nginx configuration contains values that you might want to change, such as the listening IP and port:

cuckoo web --nginx > cuckoo-web.conf
sudo cp cuckoo-web.conf /etc/nginx/sites-available/cuckoo-web.conf
sudo ln -s /etc/nginx/sites-available/cuckoo-web.conf /etc/nginx/sites-enabled/cuckoo-web.conf
sudo systemctl restart nginx

The web interface should be served by nginx now.

Starting Cuckoo

When Cuckoo starts for the first time, it creates the required database tables in the configured database type. By default this is SQLite.

Let’s start Cuckoo now. If we enable debug mode, we can see all the steps it takes along the way of starting:

cuckoo --debug

After starting, it will either start analyzing submitted files or display waiting for analyses...

Cuckoo processing instances - Advanced

When using 4+ VMs, it is recommended to use Cuckoo processing instances. These are separate processes that perform all results processing and reporting.

Normally, the processing is part of the analysis flow and performed by the main Cuckoo process. Having a lot VMs can cause a large backlog of analysis results to be processed. By moving this process to multiple dedicated processes, this problem is prevented. For more information about this, see the processing instance documentation.

Before starting processing instances, we must first configure Postgres (see [Postgres as DBMS][Postgres as DBMS].) and disable processing of results in the main Cuckoo process. Open the cuckoo.conf and change process_results = yes to process_results = no.

We can now start one or more processing instances. The syntax of the command is cuckoo process <instance name>:

cuckoo process p1

The instance(s) will process tasks that reach the completed status.

Starting Cuckoo in the background - Advanced

It might be desirable to run Cuckoo and supporting processes in the background. This is possible with supervisord. Cuckoo generates a supervisord.conf file for this in the CWD. This configuration starts Cuckoo and 4 processing instances, no other Cuckoo components. This configuration assumes the required changes in cuckoo.conf has already been made. For the full documentation on this, see the cuckoo supervisord docs.

To start setting up Cuckoo with supervisord, let’s start by installing supervisord:

sudo apt-get install supervisord

We start by telling supervisord what configuration to use:

supervisord -c /home/cuckoo/.cuckoo/supervisord.conf

Now we can now start Cuckoo as a background process and stop it when we want:

supervisorctl start cuckoo:
supervisorctl stop cuckoo:

Conclusion

After following the above steps, one may now enjoy a fully functional Cuckoo Sandbox setup with multiple VMs, network routing capabilities, the Cuckoo Web Interface, and potentially more goodies. Don’t forget to check out the extensive Cuckoo Sandbox documentation and let us know if there are questions and/or feedback.

Looking for Cuckoo Sandbox support? Check our solutions.

You may also like: