Some time ago a friend received a mysterious USB pen with a note talking about some kind of heavily persistent malware. He had that USB pen stored untouched and of course my curiosity took over. Since one should never plug in unknown USB devices into a computer (well, any USB device we purchase is unknown but that is another story) and I didn’t want to “burn” a computer just to take a look at the contents I decided to use my USB armory to build an air gap sandbox that would be harder to infect and for malware to escape from it.
The USB armory is a small computer on a USB stick, providing an ARM A8 800 MHz CPU and 512MB RAM, and it’s versatile enough to implement all kinds of interesting scenarios. One of its most interesting features for this project is secure boot, called High Assurance Boot, that allows better integrity of our USB armory platform. Amusing enough, last week there was a security advisory regarding this feature. Assuming for now that no vulnerabilities exist in its secure boot, the USB armory is a very interesting platform to have a reasonable hardware integrity level because we can fuse our PKI keys into the secure boot and just replace the microSD card per analysis target. There aren’t a lot of vectors for targeted malware to achieve hardware persistency and make the device unusable from a forensics point of view (meaning a permanent rootkit that could taint our analysis forever). The device can be ordered from Inverse Path. For this project you also need to order an host adapter – without it we can’t implement this project.
The armory can be used in two modes, host and non-host mode. The non-host mode is the default mode, which allows you to plug the device into a USB port and can access it via an IP address (it uses CDC Ethernet emulation to achieve this feature). It is essentially another computer plugged in into any computer. This configuration is interesting for hosting secure data, some kind of HSM, a secure messenger, TOR router, password manager, secure Bitcoin wallet, and so on. This wiki entry lists many other applications. Anything where hardware integrity is important because the device is so small that you can always carry it with you.
The host mode is the interesting mode for this project. In this configuration the USB armory is a standalone computer. We can attach other USB devices to it, for example, a keyboard, a USB monitor, a Ethernet and/or WiFi dongle, and so on. As long as there are Linux drivers you can attach them to the USB armory. With this mode it is very easy to build a small air gap computer – the goal for this project.
One of my first projects was to build a private travel WiFi hotspot/firewall. The idea is to have one WiFi interface connecting to the public network, and another WiFi or Ethernet dongle connecting to my private devices. This way you can isolate your machines from the public network and still use it. You power everything with a battery power pack and you have your own hotspot. These days there are many devices that do this. The key difference is that you fully control this one and avoid potential backdoors and bugs that plague this kind of device (none has secure boot for example). You can also easily add TOR routing and any other cool features (DNS tunneling to bypass annoying airport networks, etc).
Last week I gave a talk focused on physical and firmware security where I mentioned this setup and finally decided to write about my Armory Sandbox. The project has the following hardware and software requirements.
Hardware Requirements to use a USB Armory
- USB armory
- USB armory host adapter
- Serial to USB adapter (useful to debug any problems else you are blind until network is up)
- USB 2.0/3.0 HUB
- JUE130 USB 3.0 Gigabit Ethernet Adapter
- One or more 4GB+ microSD card compatibility list
- At least one micro-USB cable (to connect host adapter to power source)
- Battery power pack
Software Requirements to use a USB Armory
- Debian 8.x host (VM or not)
The design is the following:
In this design a battery power pack is used to power everything but a self-powered USB hub is also ok if portability is not an issue. The USB armory host adapter can also work as a USB condom (only power lines are connected, data is blocked) meaning that we can safely power it from a normal USB port if necessary. The power pack can also power the USB or it might need extra power if connected devices are power hungry (big hard disks for example). The USB armory connects to one end of the host adapter, while the USB hub connects to the other end. Every other USB device is of course connected to the USB hub. The USB Ethernet adapter can be connected to the network where we want to copy data to, and to increase the air gap security a firewall can be set between the USB armory network and whatever network we want to access it from. Block everything but SSH and the air gap security just increases a notch (it now requires a malware that packs a zero day to bypass our firewall).
There are a few pre-compiled installation images by Inverse Path and other Linux distributions. Their default configuration is the non-host mode. To enable the host mode on these images please refer to this document.
I did not use a pre-compiled image because at the time the Linux kernel had no native support for the USB Ethernet adapter I bought (although the manufacturer made driver available) and building my own also allows me to customize it with extra software. Very recently Inverse Path made available a Makefile to build a Debian based image (instead of copy & paste a series of commands as before).
I made a fork called Armory Sandbox that adds some additional forensics packages, and a Linux kernel configuration that includes all the necessary drivers (both for the USB Ethernet adapter but also additional file systems, HFS+ for example). We need to support common filesystems we might find in target USB devices. If you have any specific requirements you need to generate a new kernel configuration file and update the included one. The default Armory Sandbox kernel configuration is located at kernel_conf/armorysandbox_linux-4.9.config. To update the kernel configuration you need to do it the following way:
KBUILD_BUILD_USER=usbarmory KBUILD_BUILD_HOST=usbarmory ARCH=arm CROSS_COMPILE=arm-none-eabi- make menuconfig
Save the configuration file and copy over the old config file (or just save it directly from kernel configuration). If you don’t do it this way the configuration file will be built for the host machine (x86 in this case) while our target is an ARM CPU. You can use other make configuration options if you are happier with a non-graphical kernel configuration mode.
But before we can build our own image we need to install some required software in our Debian host – ARM cross compiler and software required to build the root file system.
sudo apt-get install bc binfmt-support bzip2 gcc gcc-arm-none-eabi git gnupg make parted qemu-user-static wget xz-utils zip sudo debootstrap
The Makefile verifies the kernel and U-Boot signatures so we need to import their GPG keys:
gpg --keyserver hkp://keys.gnupg.net --recv-keys 38DBBDC86092693E gpg --keyserver hkp://keys.gnupg.net --recv-keys 87F9F635D31D7652
We are now able to cross compile code for our ARM target.
To start building the Armory Sandbox image first clone the repo into the Debian host machine:
git clone https://github.com/gdbinit/armorysandbox
Edit the Makefile and add your own ssh key into SSH_KEY variable.
You can change the default Debian mirror to one that is faster for you. Just edit the DEBIAN_MIRROR variable. You might also want to change the default image size variable IMAGE_SIZE from the default 3500Mb. This assumes a minimum microSD card of 4GB. If it is bigger we can resize the partition later FAQ. If you don’t want to resize you can change this option – you just end with a bigger image that will take longer to write to the microSD card.
The default account is usbarmory and password is the same as username. You should definitely change the default password (edit the Makefile, look for CHANGEME string). We definitely don’t want malware to try to exploit a default password.
The next step is to finally build the raw image. This is done in four steps:
- Debian filesystem and packages.
- Linux kernel.
- Install kernel and U-Boot into the raw image.
If everything goes ok you end up with a armorysandbox-debian_jessie-base_image-YYYYMMDD.raw image file. Now we just need to write the image to the microSD card:
Linux (verify target from terminal using
sudo dd if=armorysandbox-debian_jessie-base_image-YYYYMMDD.raw of=/dev/sdX bs=1M conv=fsync
Mac OS X (verify target from terminal with
sudo dd if=armorysandbox-debian_jessie-base_image-YYYYMMDD.raw of=/dev/rdiskN bs=1m
You don’t need to care about making partitions in the microSD card. This command will wipe out everything in the microSD card, and the raw image we generated already contains the necessary partition information. So please be careful and double-check the target device before pressing enter.
After dd finishes writing the image you can finally remove the microSD card from the host machine and plug it into the USB armory. Power on the USB armory and connect the serial console (the header layout is available here) and verify if it booted correctly.
The default IP address is 10.1.0.1/24 without any configured gateway (at least by default we don’t want this device packets to go anywhere wild). You can just add an IP alias to the machine that will use the network to access the Armory Sandbox.
Mac OS X:
sudo ifconfig en0 alias 10.1.0.2 255.255.255.0
If this network is not ok for you just edit the Makefile before you build the image or log in via serial console and modify /etc/network/interfaces configuration file.
If you want to enable Secure Boot feature you should read Inverse Path secure boot document. Keep in mind that this feature is currently less valuable because of the mentioned security issue but it is still useful in some scenarios like this one, at least until the full vulnerability details are made public. The advisory is mostly concerned with unattended hardware and physical tampering but without full details we can’t evaluate if for example some kind of malware/exploit could be able to defeat secure boot and somehow compromise our setup and/or taint our analysis. But the biggest reason for not being included right now in this setup is that this feature involves permanent and irreversible actions.
To add packages you need to edit the Makefile and modify the line with qemu-debootstrap command. I had some problems related to packages with dependencies on Python 2.7. There were some issues with python 2.7 minimal package dependency. Not sure yet how to solve it – there are some bugs reports about this. If you really need the packages that have problems and fail to build the image you can always add them later on via apt-get or dpkg (either upload them manually, or connect the armory to the Internet).
When the Armory Sandbox finishes booting, you can log in via the serial console or SSH, plug in any supported USB device, mount it, and analyze its filesystem, or image it for analysis on another machine. After you finish analysis you can just discard the microSD (or sell them on EBay) if you want to be really safe, or just wipe it out and rewrite the Armory Sandbox image you built. This brings an additional problem, how to securely wipe the microSD card: self wipe, another isolated device just to wipe? We need to be careful to not break the air gap with a microSD card that might be potentially tainted by the USB devices we plugged in.
This project is far from the first to attempt to build an isolated USB analysis system. For example, Circl.lu has previously built CIRCLean USB Sanitizer using a Raspberry Pi device. The problem with this device is that it tries to automatically convert untrusted documents into another format, and more important to me, it mixes storage devices – the same “isolated” device accesses the bad USB and the good USB. It is breaking the air gap by design. I prefer a solution where the access is made over the network because we can add a firewall between the isolated device and the desktop machine. Also I don’t want to automate any data conversion, I just want an air gap. Of course CIRCLean project can be modified to accommodate these changes. Raspberry Pi doesn’t have a secure boot feature on its default package (although there are some available add-ons to achieve this), and that was a big plus on the USB armory, at least until vulnerabilities were found (my original setup was created way before these vulnerabilities were announced).
The USB armory is a super interesting platform and with some creativity really nice projects can be made out of it. You should definitely purchase one and explore it.