HackFortressOS - Adventures with Buildroot
About The Project
Arch Cloud Labs’ last three blog posts were diving into different aspects of IoT/embedded vulnerabilities. Coming off of these bug hunting adventures, I wanted to build a unique set of Capture The Flag (CTF) challenges for this year’s Hack Fortress. To do this, I referenced OWASP’s Top 10 for IoT and Buildroot to build the custom operating system for a Raspberry Pi 1 that was deemed “HackFortress OS”. This blog post will give a high level overview on how Buildroot was used to make a custom platform along with a discussion on some of the challenges that were spun off from HackFortress OS.
Buildroot - Make, but for Entire Embedded Systems
Buildroot is a build system that enables end users to build custom operating systems for a given embedded platform. Ultimately, you pick a Linux kernel, select the options for the kernel/packages/etc., and end up with your final embedded operating system. Obtaining the latest release and listing the contents of the board directory shows the various platforms Buildroot supports. Below is a truncated output of supported boards. Notably, we see “Raspberry Pi” as in the first Raspberry Pi made. A platform that’s over ten years old, and just the appropriate board to build a vulnerable embedded system to let hackers poke at for the ShmooCon conference weekend.
ls ~/buildroot/board/
minnowboard openblocks qemu raspberrypi2 raspberrypicm4io-64 sipeed
nexbox orangepi qmtech raspberrypi3 raspberrypizero2w solidrun
nezha pandaboard radxa raspberrypi3-64 roseapplepi spike
octavo pc raspberrypi raspberrypi4 seeed stmicroelectronics
olimex pcengines raspberrypi0 raspberrypi4-64 sheevaplug synopsys
olpc pine64 raspberrypi0w raspberrypicm4io sifive technexion
With Raspbery Pi identified as the target system, the next step is to build a default configuration to modify to the end user’s desired needs.
buildroot $> make raspberrypi_defconfig
#
# configuration written to /home/dllcoolj/buildroot/.config
#
➜ buildroot
Those familiar with building custom kernels and the ncurses view provided by make menuconfig
will be right at home with this next section. The initial configuration menu contains numerous submenus that allow Buildroot users a lot of flexibility when it comes to building a custom image. Prior to going forth and exploring all of the submenus, I recommend you build a simple default config (make defconfig
) to make sure your hardware works as expected and you gain familiarity with the build process. Diving into the submenus, here’s a brief breakdown of what’s available and relevant to how HackFortress OS was built:
- Toolchain: This is where you can specify target options for the underlying architecture you’re using. The Raspberry Pi is an ARM based platform, but you can specify additional architecture options should you be building on a device where the ARM chip supports it.
This is another example of why building the
defconfig
and tweaking from a known good state is a recommended practice.
- Build options: This submenu specifies caching options for the actual building of the embedded system. Additionally, here is where you can enable or disable core security features that help prevent against memory corruption. One of the challenges for competitors this year was a basic buffer overflow, and naturally, we had this option disabled.
- Target packages: This submenu allows you to specify what packages you want on the embedded device. It also includes several popular Python packages you would normally expect to install through pip. A challenge this year was exploiting a vulnerable web API which required Flask. While the Raspberry Pi 1 took about five seconds to launch the Flask app (thus really showing its age), Buildroot had no problems running a recent version of Flask for such an old device.
- Filesystem options: This submenu allows you to specify the target filesystem for your device. For CTFs this was a big choice as your competitors are going to be leveraging a variety of forensic tools to carve out files. It’s also important to consider how large of a file system you’ll be giving the competitors as no one wants to transferred a 100GB image where the vast amount of image is effectively empty space.
After making your changes, simple execute make
and the build process for your final image will be produced in the output/images
directory.
[dllcoolj@thonkpad images]$ pwd
/home/dllcoolj/buildroot/output/images
[dllcoolj@thonkpad images]$ ls -l
total 154052
-rwxr-xr-x 1 dllcoolj docker 27696 Jan 7 20:58 bcm2708-rpi-b.dtb
-rwxr-xr-x 1 dllcoolj docker 27967 Jan 7 20:58 bcm2708-rpi-b-plus.dtb
-rwxr-xr-x 1 dllcoolj docker 27581 Jan 7 20:58 bcm2708-rpi-cm.dtb
-rw-r--r-- 1 dllcoolj docker 33554432 Jan 7 20:58 boot.vfat
-rw-r--r-- 1 dllcoolj docker 125829120 Jan 7 20:58 rootfs.ext2 // file system
lrwxrwxrwx 1 dllcoolj docker 11 Jan 7 20:58 rootfs.ext4 -> rootfs.ext2
drwxr-xr-x 1 dllcoolj docker 118 Jan 7 20:45 rpi-firmware
-rw-r--r-- 1 dllcoolj docker 159384064 Jan 7 20:58 sdcard.img // the Raspberry Pi image to
-rw-r--r-- 1 dllcoolj docker 6012640 Jan 7 20:58 zImage // the kernel
At this point you should have a bootable image for your target device. Logging into HackFortressOS (HFOS) we see a whopping 32MB of RAM used. As you can see, when you build a “farm-to-table” embedded OS, you can really optimize out all pesky those security features and get the most out of your embedded system.
# hostname
hfos
# free -h
total used free shared buff/cache available
Mem: 394.2M 29.0M 332.4M 116.0K 32.7M 355.4M
Swap: 0 0 0
Making Things Boot - Exploring Init Systems
Buildroot lets you specify what you’d like your embedded OS to have as an init system. Choices include Systemd, SysV, and “BusyBox’s Init” scripts. Hackfortress OS uses BusyBox’s init scripts, and custom modifications are placed within output/target/etc/init.d. Why use BusyBox’s init scripts vs SysV? This manifesto was enough of a justification for me, and it was simple enough to throw together and get running. This file structure is what ends up getting built into the final filesystem image.
/home/dllcoolj/buildroot/output/target/etc/init.d
[dllcoolj@thonkpad init.d]$ ls -l
total 28
-rwxr-xr-x 1 dllcoolj docker 423 Jan 7 20:43 rcK
-rwxr-xr-x 1 dllcoolj docker 408 Jan 7 20:43 rcS
-rwxr-xr-x 1 dllcoolj docker 1243 Jan 7 20:45 S01seedrng
-rwxr-xr-x 1 dllcoolj docker 1012 Jan 7 20:43 S01syslogd
-rwxr-xr-x 1 dllcoolj docker 1004 Jan 7 20:43 S02klogd
-rwxr-xr-x 1 dllcoolj docker 2804 Jan 7 20:43 S02sysctl
-rwxr-xr-x 1 dllcoolj docker 438 Jan 7 20:43 S40network
Building Challenges from The Custom OS
With HackFortress OS built, now we can move onto identifying the challenges to spin off of the concept of a vulnerable embedded system. This project ultimately this produced a series of challenges that covered the following items from the OWASP IoT Top Ten:
- Hardcoded passwords/keys (1/10 on OWASP IoT 2018)
- Insecure network services (2/10 on OWASP IoT 2018)
- An insecure update mechanism (4/10 on OWASP IoT 2018)
These three tenets of vulnerability patterns led to the creation of a handful of fun puzzles. Here’s three that I liked the most:
-
HFOS API The HFOS API was a bytecode compiled Python Flask application that the competitor must reverse engineer to identify vulnerable endpoints. Ultimately there was a vulnerable code path that led to arbitrary file upload and execution.
-
HFOS Secure Firmware Update* For the “HFOS Secure Firmware Update” puzzle, the SDCard image that was produced from buildroot was then wrapped into a custom file format. This fileformat was then trasnferred to an “upstream staging server” via TFTP. Competitors had to extract the image from the TFTP stream and then reverse the image format to extract the SDCard image. Once the image was extract and mounted, the flag was obtained.
-
HFOS Lost SSH Keys Derek, a fellow Hack Fortress judge always loses his SSH keys. To make fun of this, I created a puzzle where you carve out a file system and find over 1k ssh keys. The competitor must then brute force the key combination to successfully log into the destination host.
Conclusion
Buildroot is a really cool utility that enables any Linux enthusiast the ability to build their own embedded OS. For purposes of CTF creation, there’s countless possibilities and scenarios where this utility can be employed to create a unique experience for your competitors. Thank you for reading and hackers thank you for playing. I look forward to next year where the last Hack Fortress at Shmoocon will be held.