Another Solution to the USBKill.py Problem

by Jack D. Ripper

As a follow-up to "USBkill - A Program for the Very Paranoid Computer User" (32:4), here is the solution used in Ninja OS, a live operating system designed for USB drives.

What we do is keep a Bash script resident in memory that cycles a loop every third of a second and checks that whatever physical device is mounted on /boot (which is always the physical USB stick) remains present.  If this is gone, it reboots.

Also included are some anti-tamper features such as trapping the escapes into reboots as well as looking to make sure needed binaries exist.

The script requires a statically copied version of BusyBox with the correct applets copied tmpfs based /tmp on boot.  The BusyBox compile is also responsible for the work of the self-destruct feature.  It's also compiled to only have the bare amount of applets needed to reduce complexity the chance it can be used by an attacker.

The result: simply pull the USB drive and the system reboots with a call to reboot -f from a static compiled BusyBox.

/usr/share/scripts_drivewatch.sh:

#!/bin/bash
. /usr/share/scripts/liveos_boilerplate.sh
#
#  Written for Ninja OS by the development team.
#  licensed under the GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
#
# This script runs at start up, stays resident and watches for the OS drive to
# be unplugged. If so it shuts the system down.

TICK=".0333"

tamper_reboot(){
    # This function reboots the machine if tampering is found with any of
    # components. We try a few shutdown methods until one sticks
    notify-send "Tampering Detected" "Rebooting..." --icon=software-update-urgent
    echo "Tampering Detected, Rebooting"
    /tmp/emergency_bin/busybox reboot -f
    /var/emergency_bin/busybox reboot -f
    /usr/bin/reboot -f
    systemctl --force reboot
}

tamper_check(){
    # This function checks if any of the binaries needed for emergency actions
    # are tampered with. busybox is needed for this script, and pv is needed for
    # zeroize.
    [ -f /tmp/emergency_bin/busybox ] || tamper_reboot
    [ -f /var/emergency_bin/pv ] || tamper_reboot
}
shutdown_check() {
   # If this script is killed by shutdown, regardless, it will reboot the system
   # Therefor the shutdown command will reboot. The solution is to check for
   # shutdown status before checking for tampering.
   local status_reboot=$(systemctl is-active systemd-reboot.service)
   local status_poweroff=$(systemctl is-active systemd-poweroff.service)
   [ $status_poweroff == "active" ] && poweroff -f
   [ $status_reboot == "active" ] && reboot -f
}

# If someone tries to disrupt the script while running, reboot.
trap "tamper_reboot" 1 2 9 15 17 19 23

while [ -b $BOOTDEV ];do
     # Every tick we check if the system has been tampered with
     shutdown_check
     tamper_check
     /tmp/emergency_bin/busybox sleep ${TICK}
done

#reboot the system.
/tmp/emergency_bin/busybox reboot -f

The important part from /usr/share/script/liveos_boilerplate.sh:

BOOTPART=$(mount | grep /boot | cut -d " " -f 1)
BOOTDEV=${BOOTPART:0:$((${#BOOTPART}-1))}

The important parts from /usr/share/script/parachute.sh:

#!/bin/bash
#
# Written for the NinjaOS by the development team.
# licensed under the GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
# Lets make our emergency parachute with our specially compiled stripped down
# version of busybox
mkdir /tmp/emergency_bin
cp /var/emergency_bin/busybox /tmp/emergency_bin/
# This is done at boot time, instead of install time because it puts the file in
# the top AUFS layer which is tmpfs which is in ram, which does not go away with
# the boot media is removed.
chmod 555 /tmp/emergency_bin/busybox

/etc/systemd.system/multi-user.target.wants/emergency_reboot.service:

[Unit]
Description=Emergency Parachute

[Service]
Type=simple
ExecStart=/usr/share/scripts/drive_watch.sh
ExecStop=/usr/bin/true
TimeoutStopSec=1
StandardOutput=tty
RemainAfterExit=no

[Install]
WantedBy=multi-user.target

/etc/systemd.system/multi-user.target.wants/parachute.service:

[Unit]
Description=Parachute for emergency RAM based shutdown
Before=NetworkManager.service

[Service]
Type=oneshot
ExecStart=-/usr/share/scripts/parachute.sh
TimeoutSec=0
StandardInput=tty
RemainAfterExit=yes

The emergency shutdown is one of the key features of Ninja OS.

Ninja OS with USB flash drives, most of which either come with, or have holes for, small lanyards you can tie around your wrist.  Combining this feature with physical security of the lanyard if applied correctly would pull the drive out of the USB socket if the user is physically removed from the console.

It's a fairly good deterrent against trying to gain access to data by physical theft.

For future changes in Ninja OS, we have a git repository at gitlab.com/ninjaos/ninjaos.

Our home page is at ninjaos.org and on IRC we are in the #ninjaos channel on irc.freenode.net.

Code: scripts_drivewatch.sh

Code: parachute.sh  Includes systemd service files.

Return to $2600 Index