Created
November 10, 2017 19:33
-
-
Save HacKanCuBa/96abf0254de9caa1476ef3daee0ec812 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
################################################################################ | |
# | |
# ~~~~ Emergency Lockdown ~~~~ | |
# Forces a lockdown on the system: kills the keys and luks headers, | |
# then reboots. | |
# Copyright (C) 2015 by HacKan | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
################################################################################ | |
# | |
# Version: 1.16 (tested) | |
# Add this to the sudoers file or as a new file: | |
# visudo -sf /etc/sudoers.d/emergencylockdown | |
# %USERGROUP ALL = NOPASSWD: /usr/bin/emergencylockdown | |
# Where %USERGROUP is your user group, i.e.: %hackan | |
# so that you can execute this script as a command without password | |
# be careful! | |
# | |
################################################################################ | |
trap ctrl_c INT | |
declare -r true=1 | |
declare -r false= | |
# Config | |
# Label of the device holding your keys | |
# (as in /dev/disk/by-label/<device_label>) | |
declare -r KEY_LABEL="<your_pendrive_label>" | |
# Enable or disable debug mode, which allows to do a dry-run | |
DEBUG=$true # DISABLE DEBUG MODE ON PRODUCTION! | |
# <> | |
function ctrl_c() { | |
[ "${DEBUG}" ] && exit 1 || echo "ah ah ah! you didn't say the magic word!" | |
} | |
function get_rand_str() { | |
# Returns a 7 char random hex string (not crypto safe!) | |
# Use: STR="$(get_rand_str)" | |
echo $RANDOM | md5sum | head -c 7 | |
} | |
function e_debug() { | |
if [ "${DEBUG}" ]; then | |
echo "DEBUG### $@" | |
fi | |
} | |
function destroy_file() { | |
# Destroys a file using shred | |
local FILE="$1" | |
shred -fzn 5 "${FILE}" > /dev/null 2>&1 | |
if [ $? -ne 0 ]; then | |
# Repeat. Sometimes, shred fails the first time, for unknow reasons | |
# but goes well the second time. | |
# However I'm not looping it until it works, it's not that important | |
# and I must hurry! | |
shred -fzn 5 "${FILE}" > /dev/null 2>&1 | |
fi | |
} | |
function fake_key() { | |
local KEY="$1" | |
dd status=none if=/dev/urandom of="${KEY}" bs=1024 count=1 | |
} | |
if [ "$(whoami)" = "root" ]; then | |
declare -r TMPFS_MOUNT="/root/$(get_rand_str)" | |
declare -ri TMPFS_SIZE=$(( 25 + ($RANDOM % 100) )) | |
declare -r HEADERFNAME="$(get_rand_str)" | |
if [ "${DEBUG}" ]; then | |
echo "Emergency lockdown taking place, stand by... DEBUG MODE" | wall | |
else | |
echo "Emergency lockdown taking place, stand by..." | wall | |
logger "Emergency lockdown taking place, stand by..." | |
fi | |
# List of LUKS devices | |
declare -ra LUKSDEV=( $(lsblk --fs -rno NAME,FSTYPE | grep crypto_LUKS | cut -f1 -d " ") ) | |
echo "Devices to lockdown (${#LUKSDEV[@]}): ${LUKSDEV[@]}" | |
echo -en "Working..." | |
# Overwrites header + keys sequentially, increasing size of the data overwritten. | |
# Each iteration adds 1MB of data overwritten | |
# Uses the luks header size as blocksize | |
# WARNING: makes the device COMPLETELY UNRECOVERABLE, even having luks header backup | |
#for i in {1..10}; do | |
# for SDXX in "${LUKSDEV[@]}"; do | |
# DEV="/dev/${SDXX}" | |
# SIZE_LUKSHEAD=$(cryptsetup luksDump "${DEV}" | grep "Payload offset:" | cut -f2) | |
# #echo $DEV | |
# #echo $SIZE_LUKSHEAD | |
# dd status=none if=/dev/urandom of="${DEV}" bs=${SIZE_LUKSHEAD} count=$(( ${i} * 1048576 / ${SIZE_LUKSHEAD} )) | |
# #echo "$(( ${i} * 1048576 / ${SIZE_LUKSHEAD} ))" | |
# sync | |
# done | |
# echo -en "." | |
#done | |
#echo | |
# For a less overkill aproach, lets: backup header to get size, | |
# overwrite dev, destroy header | |
e_debug "TMPFS_SIZE=${TMPFS_SIZE}M" | |
e_debug "TMPFS_MOUNT=${TMPFS_MOUNT}" | |
e_debug "Header file: ${TMPFS_MOUNT}/${HEADERFNAME}" | |
mkdir -p "${TMPFS_MOUNT}" | |
mount -t tmpfs -o size="${TMPFS_SIZE}M" tmpfs "${TMPFS_MOUNT}" | |
# Even if the mount fails for some reason, we can still write files there | |
for i in {1..5}; do | |
for SDXX in "${LUKSDEV[@]}"; do | |
DEV="/dev/${SDXX}" | |
e_debug "DEV=${DEV}" | |
# Get header file | |
cryptsetup --batch-mode luksHeaderBackup "${DEV}" --header-backup-file "${TMPFS_MOUNT}/${HEADERFNAME}" > /dev/null 2>&1 | |
# Calculate sizes | |
SIZE_HEADER=$(du -b "${TMPFS_MOUNT}/${HEADERFNAME}" | cut -f1) | |
SIZE_LUKSHEAD=$(cryptsetup --batch-mode luksDump "${DEV}" | grep "Payload offset:" | cut -f2) | |
e_debug "SIZE_HEADER=$SIZE_HEADER" | |
e_debug "SIZE_LUKSHEAD=$SIZE_LUKSHEAD" | |
e_debug "COUNT=$(( ${SIZE_HEADER} / ${SIZE_LUKSHEAD} ))" | |
# Destroy device header | |
DEVDD= | |
if [ "${DEBUG}" ]; then | |
DEVDD="${SDXX}" | |
else | |
DEVDD="${DEV}" | |
fi | |
dd status=none if=/dev/urandom of="${DEVDD}" bs=${SIZE_LUKSHEAD} count=$(( ${SIZE_HEADER} / ${SIZE_LUKSHEAD} )) | |
# Just in case the division operation isnt integer | |
dd status=none if=/dev/urandom of="${DEVDD}" bs=${SIZE_HEADER} count=1 | |
# Destroy header file | |
destroy_file "${TMPFS_MOUNT}/${HEADERFNAME}" | |
# Repeat over the same file | |
sync | |
done | |
echo -en "." | |
done | |
# Remove header file | |
shred -ufzn 1 "${TMPFS_MOUNT}/${HEADERFNAME}" | |
# Overwrite | |
DELFNAME="$(get_rand_str)" | |
e_debug "DELFNAME=${DELFNAME}" | |
# Instead of filling the device, I set a size in case the tmpfs mount failed | |
dd status=none if=/dev/zero of="${TMPFS_MOUNT}/${DELFNAME}" bs=4096 count=$(( ${TMPFS_SIZE} * 256 )) | |
destroy_file "${TMPFS_MOUNT}/${DELFNAME}" | |
umount "${TMPFS_MOUNT}" | |
rm -rf "${TMPFS_MOUNT}" | |
echo "All done with devices, now destroy the keys" | |
# Try to destroy the keys, just in case | |
declare -r KEY_DEV="/dev/disk/by-label/${KEY_LABEL}" | |
# Verify that we have an actual device here | |
if [ -b "${KEY_DEV}" ]; then | |
# Mount device | |
KEY_MOUNT= | |
if [ "$(mount | grep ${KEY_LABEL})" ]; then | |
# Already mounted, get directory | |
KEY_MOUNT="$(mount | grep ${KEY_LABEL} | cut -f3 -d ' ')" | |
else | |
# Make dir and mount | |
KEY_MOUNT="/root/$(get_rand_str)" | |
mkdir -p "${KEY_MOUNT}" | |
mount -t auto "${KEY_DEV}" "${KEY_MOUNT}" | |
fi | |
e_debug "KEY_MOUNT=${KEY_MOUNT}" | |
# Note: dont use " with the ls command!! | |
for KEYFILE in $(ls ${KEY_MOUNT}/*.key "${KEY_MOUNT}/.hidden"); do | |
e_debug "KEYFILE=${KEYFILE}" | |
if [ "${DEBUG}" ]; then | |
e_debug "shred -ufzn 5 ${KEYFILE} ..." | |
else | |
destroy_file "${KEYFILE}" | |
fake_key "${KEYFILE}" | |
fi | |
done | |
umount "${KEY_MOUNT}" | |
rmdir "${KEY_MOUNT}" > /dev/null 2>&1 | |
else | |
echo "Key device ${KEY_DEV} not found, skipping..." | |
fi | |
echo "All done" | |
echo "Good bye :)" | wall | |
e_debug "Remember to disable debug mode!!" | |
[ "${DEBUG}" ] && { echo "Emergency lockdown DEBUG: poweroff" | wall; } || poweroff | |
else | |
# Try to rerun | |
e_debug "Reruning: sudo $0" | |
sudo $0 | |
exit | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment