Приветствую.
Представим ситуацию, где в вашу сторону исходит угроза принуждения к вводу пароля вашего девайса во время загрузки.
Разберем настройку механизма аварийного уничтожения данных в Qubes OS. Суть простая: создаете специальный пароль, и если введете его при загрузке вместо обычного, система уничтожит все ключи шифрования. Данные станут нечитаемыми навсегда.
Реализация этого механизма заключается во внедрении скрипта, который помещается между процессом загрузки и стандартной расшифровкой диска. Каждый раз, когда вы вводите пароль, этот скрипт проверяет его хеш против заранее сохранённого хеша nuke пароля . Если введён обычный пароль диск расшифровывается как обычно, но если будет введен nuke пароль, то сразу же будет вызвана процедура уничтожения всех ключевых слотов LUKS и начнется перезапись заголовков случайными данными, что делает диск навсегда нечитаемым. Весь этот процесс происходит бесшовно и незаметно для того, кто получил физический доступ к вашему устройству.
Сразу предупреждаю: не тестируйте скрипт на вашем рабочем девайсе с данными. Вы можете установить и настроить модуль, но не вводите пароль nuke для тестирования. Одна ошибка или опечатка, и вы потеряете всё. Для тестов используйте отдельный девайс.
Установка:
Все делаем в dom0.
Сначала ставим OpenSSL и создаем каталог для хранения хеша:
Теперь нужно придумать и ввести nuke password. Выполните эту команду:
Введите пароль. Символы не будут отображаться на экране, это нормально.
Дальше генерируем хеш. Эта команда снова попросит пароль, сгенерирует случайную строку для защиты хеша и сохранит хеш в файл:
Проверьте, что хеш создался правильно:
Должна быть строка типа
Если видите такое, всё в порядке.
Теперь проверим, что пароль правильно сверяется с хешем:
Должно написать `MATCH`. Если пишет `NO MATCH`, что-то сделали не так, перечитывайте и начинайте заново.
Создаем модуль для dracut
Создаем каталог:
Записываем скрипт установки модуля:
Делаем скрипт исполняемым:
Теперь пересобираем образ загрузки, чтобы наш модуль туда попал:
Смотрите в вывод. Там должны появиться строки вроде этих:
Если видите такое, значит модуль успешно встроился. Готово.
Что важно понимать
Этот механизм защищает только от одного сценария: когда вас принуждают ввести пароль при загрузке. Он не защищает от того, что противник сделал копию диска до этого момента. Он не защищает, если сессия уже загружена. Он не защищает от анализа оперативной памяти.
Представим ситуацию, где в вашу сторону исходит угроза принуждения к вводу пароля вашего девайса во время загрузки.
Разберем настройку механизма аварийного уничтожения данных в Qubes OS. Суть простая: создаете специальный пароль, и если введете его при загрузке вместо обычного, система уничтожит все ключи шифрования. Данные станут нечитаемыми навсегда.
Реализация этого механизма заключается во внедрении скрипта, который помещается между процессом загрузки и стандартной расшифровкой диска. Каждый раз, когда вы вводите пароль, этот скрипт проверяет его хеш против заранее сохранённого хеша nuke пароля . Если введён обычный пароль диск расшифровывается как обычно, но если будет введен nuke пароль, то сразу же будет вызвана процедура уничтожения всех ключевых слотов LUKS и начнется перезапись заголовков случайными данными, что делает диск навсегда нечитаемым. Весь этот процесс происходит бесшовно и незаметно для того, кто получил физический доступ к вашему устройству.
Сразу предупреждаю: не тестируйте скрипт на вашем рабочем девайсе с данными. Вы можете установить и настроить модуль, но не вводите пароль nuke для тестирования. Одна ошибка или опечатка, и вы потеряете всё. Для тестов используйте отдельный девайс.
Установка:
Все делаем в dom0.
Сначала ставим OpenSSL и создаем каталог для хранения хеша:
Bash:
sudo qubes-dom0-update openssl
Bash:
sudo mkdir -p /etc/cryptsetup-nuke-ng
Bash:
sudo chmod 700 /etc/cryptsetup-nuke-ng
Теперь нужно придумать и ввести nuke password. Выполните эту команду:
Код:
read -rs NUKE_PASS
Код:
echo
Введите пароль. Символы не будут отображаться на экране, это нормально.
Дальше генерируем хеш. Эта команда снова попросит пароль, сгенерирует случайную строку для защиты хеша и сохранит хеш в файл:
Bash:
read -rs NUKE_PASS; echo; SALT=$(tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 8); printf '%s' "$NUKE_PASS" | openssl passwd -6 -salt "$SALT" -stdin | sudo tee /etc/cryptsetup-nuke-ng/password_hash >/dev/null; sudo chmod 600 /etc/cryptsetup-nuke-ng/password_hash; NUKE_PASS=$(dd if=/dev/urandom bs=64 count=1 2>/dev/null | base64); unset NUKE_PASS
Проверьте, что хеш создался правильно:
Bash:
sudo cat /etc/cryptsetup-nuke-ng/password_hash
Должна быть строка типа
Код:
`$6$salt$очень_длинная_строка_хеша...`
Теперь проверим, что пароль правильно сверяется с хешем:
Bash:
read -rs TEST_PASS; echo; HASH=$(sudo cat /etc/cryptsetup-nuke-ng/password_hash); SALT=$(echo "$HASH" | sed 's/^\$6\$\([^$]*\)\$.*/\1/'); printf '%s' "$TEST_PASS" | openssl passwd -6 -salt "$SALT" -stdin | grep -q "^$(sudo cat /etc/cryptsetup-nuke-ng/password_hash)$" && echo "MATCH" || echo "NO MATCH"; unset TEST_PASS
Должно написать `MATCH`. Если пишет `NO MATCH`, что-то сделали не так, перечитывайте и начинайте заново.
Создаем модуль для dracut
Создаем каталог:
Bash:
sudo mkdir -p /usr/lib/dracut/modules.d/99nuke-systemd
Записываем скрипт установки модуля:
sudo tee /usr/lib/dracut/modules.d/99nuke-systemd/module-setup.sh << 'EOF'
#!/bin/bash
check() {
if [ ! -f /etc/cryptsetup-nuke-ng/password_hash ]; then
derror "nuke password hash not found"
return 1
fi
return 0
}
depends() {
echo systemd crypt
return 0
}
install() {
inst /etc/cryptsetup-nuke-ng/password_hash
inst_multiple dd mktemp rm cat printf stty cryptsetup openssl systemd-ask-password
local real_binary=""
for path in "$initdir/usr/bin/systemd-cryptsetup" "$initdir/usr/lib/systemd/systemd-cryptsetup"; do
if [ -f "$path" ] && [ ! -L "$path" ]; then
real_binary="$path"
break
fi
done
if [ -z "$real_binary" ]; then
real_binary=$(find "$initdir" -name "systemd-cryptsetup" -type f ! -type l 2>/dev/null | head -n1)
fi
if [ -z "$real_binary" ]; then
dfatal "Cannot find real systemd-cryptsetup binary in initramfs"
return 1
fi
dinfo "Found systemd-cryptsetup at: $real_binary"
mv "$real_binary" "${real_binary}.real"
cat > "$real_binary" << 'WRAPPER'
#!/bin/bash
set -e
NUKE_HASH_FILE="/etc/cryptsetup-nuke-ng/password_hash"
SYSTEMD_CRYPTSETUP="${0}.real"
if [ ! -f "$NUKE_HASH_FILE" ]; then
exec "$SYSTEMD_CRYPTSETUP" "$@"
fi
NUKE_HASH=$(cat "$NUKE_HASH_FILE")
NUKE_SALT=$(echo "$NUKE_HASH" | sed 's/^\$6\$\([^$]*\)\$.*/\1/')
if [ "$1" = "attach" ]; then
KEYFILE="$4"
DEVICE="$3"
NAME="$2"
if [ -n "$KEYFILE" ] && [ "$KEYFILE" != "-" ] && [ "$KEYFILE" != "none" ]; then
exec "$SYSTEMD_CRYPTSETUP" "$@"
fi
PASSWORD=$(systemd-ask-password --no-tty "Please enter passphrase for disk $NAME:" 2>/dev/null || true)
if [ -z "$PASSWORD" ] && [ -t 0 ]; then
printf 'Please unlock disk %s: ' "$NAME" >&2
stty -echo 2>/dev/null || true
IFS= read -r PASSWORD
stty echo 2>/dev/null || true
printf '\n' >&2
fi
if [ -n "$PASSWORD" ]; then
COMPUTED=$(printf '%s' "$PASSWORD" | openssl passwd -6 -salt "$NUKE_SALT" -stdin)
if [ "$COMPUTED" = "$NUKE_HASH" ]; then
printf '[NUKE] Nuke password detected! Destroying keys...\n' >&2
for slot in 0 1 2 3 4 5 6 7; do
cryptsetup luksKillSlot "$DEVICE" "$slot" 2>/dev/null || true
done
if command -v dd >/dev/null 2>&1; then
dd if=/dev/urandom of="$DEVICE" bs=1M count=4 2>/dev/null || true
fi
printf '[NUKE] Device %s nuked.\n' "$DEVICE" >&2
exit 1
fi
fi
KEYFILE=$(mktemp -p /dev/shm 2>/dev/null || mktemp)
chmod 600 "$KEYFILE"
printf '%s' "$PASSWORD" > "$KEYFILE"
PASSWORD=""
set +e
"$SYSTEMD_CRYPTSETUP" "$1" "$2" "$3" "$KEYFILE" "$5"
STATUS=$?
set -e
dd if=/dev/urandom of="$KEYFILE" bs=512 count=1 2>/dev/null || true
rm -f "$KEYFILE"
exit $STATUS
fi
exec "$SYSTEMD_CRYPTSETUP" "$@"
WRAPPER
chmod +x "$real_binary"
if [ -L "$initdir/usr/lib/systemd/systemd-cryptsetup" ]; then
rm -f "$initdir/usr/lib/systemd/systemd-cryptsetup"
ln -s "../../bin/systemd-cryptsetup" "$initdir/usr/lib/systemd/systemd-cryptsetup"
fi
dinfo "Installed nuke wrapper for systemd-cryptsetup"
}
EOF
#!/bin/bash
check() {
if [ ! -f /etc/cryptsetup-nuke-ng/password_hash ]; then
derror "nuke password hash not found"
return 1
fi
return 0
}
depends() {
echo systemd crypt
return 0
}
install() {
inst /etc/cryptsetup-nuke-ng/password_hash
inst_multiple dd mktemp rm cat printf stty cryptsetup openssl systemd-ask-password
local real_binary=""
for path in "$initdir/usr/bin/systemd-cryptsetup" "$initdir/usr/lib/systemd/systemd-cryptsetup"; do
if [ -f "$path" ] && [ ! -L "$path" ]; then
real_binary="$path"
break
fi
done
if [ -z "$real_binary" ]; then
real_binary=$(find "$initdir" -name "systemd-cryptsetup" -type f ! -type l 2>/dev/null | head -n1)
fi
if [ -z "$real_binary" ]; then
dfatal "Cannot find real systemd-cryptsetup binary in initramfs"
return 1
fi
dinfo "Found systemd-cryptsetup at: $real_binary"
mv "$real_binary" "${real_binary}.real"
cat > "$real_binary" << 'WRAPPER'
#!/bin/bash
set -e
NUKE_HASH_FILE="/etc/cryptsetup-nuke-ng/password_hash"
SYSTEMD_CRYPTSETUP="${0}.real"
if [ ! -f "$NUKE_HASH_FILE" ]; then
exec "$SYSTEMD_CRYPTSETUP" "$@"
fi
NUKE_HASH=$(cat "$NUKE_HASH_FILE")
NUKE_SALT=$(echo "$NUKE_HASH" | sed 's/^\$6\$\([^$]*\)\$.*/\1/')
if [ "$1" = "attach" ]; then
KEYFILE="$4"
DEVICE="$3"
NAME="$2"
if [ -n "$KEYFILE" ] && [ "$KEYFILE" != "-" ] && [ "$KEYFILE" != "none" ]; then
exec "$SYSTEMD_CRYPTSETUP" "$@"
fi
PASSWORD=$(systemd-ask-password --no-tty "Please enter passphrase for disk $NAME:" 2>/dev/null || true)
if [ -z "$PASSWORD" ] && [ -t 0 ]; then
printf 'Please unlock disk %s: ' "$NAME" >&2
stty -echo 2>/dev/null || true
IFS= read -r PASSWORD
stty echo 2>/dev/null || true
printf '\n' >&2
fi
if [ -n "$PASSWORD" ]; then
COMPUTED=$(printf '%s' "$PASSWORD" | openssl passwd -6 -salt "$NUKE_SALT" -stdin)
if [ "$COMPUTED" = "$NUKE_HASH" ]; then
printf '[NUKE] Nuke password detected! Destroying keys...\n' >&2
for slot in 0 1 2 3 4 5 6 7; do
cryptsetup luksKillSlot "$DEVICE" "$slot" 2>/dev/null || true
done
if command -v dd >/dev/null 2>&1; then
dd if=/dev/urandom of="$DEVICE" bs=1M count=4 2>/dev/null || true
fi
printf '[NUKE] Device %s nuked.\n' "$DEVICE" >&2
exit 1
fi
fi
KEYFILE=$(mktemp -p /dev/shm 2>/dev/null || mktemp)
chmod 600 "$KEYFILE"
printf '%s' "$PASSWORD" > "$KEYFILE"
PASSWORD=""
set +e
"$SYSTEMD_CRYPTSETUP" "$1" "$2" "$3" "$KEYFILE" "$5"
STATUS=$?
set -e
dd if=/dev/urandom of="$KEYFILE" bs=512 count=1 2>/dev/null || true
rm -f "$KEYFILE"
exit $STATUS
fi
exec "$SYSTEMD_CRYPTSETUP" "$@"
WRAPPER
chmod +x "$real_binary"
if [ -L "$initdir/usr/lib/systemd/systemd-cryptsetup" ]; then
rm -f "$initdir/usr/lib/systemd/systemd-cryptsetup"
ln -s "../../bin/systemd-cryptsetup" "$initdir/usr/lib/systemd/systemd-cryptsetup"
fi
dinfo "Installed nuke wrapper for systemd-cryptsetup"
}
EOF
Делаем скрипт исполняемым:
Bash:
sudo chmod +x /usr/lib/dracut/modules.d/99nuke-systemd/module-setup.sh
Теперь пересобираем образ загрузки, чтобы наш модуль туда попал:
Bash:
sudo dracut --force --verbose
Смотрите в вывод. Там должны появиться строки вроде этих:
dracut: *** Including module: nuke-systemd ***
dracut: Found systemd-cryptsetup at: /var/tmp/dracut.XXXXXX/initramfs/usr/bin/systemd-cryptsetup
dracut: Installed nuke wrapper for systemd-cryptsetup
Если видите такое, значит модуль успешно встроился. Готово.
Что важно понимать
Этот механизм защищает только от одного сценария: когда вас принуждают ввести пароль при загрузке. Он не защищает от того, что противник сделал копию диска до этого момента. Он не защищает, если сессия уже загружена. Он не защищает от анализа оперативной памяти.
!
Автор объявления —
непроверенный пользователь
.
Используйте
гарант-сервис форума
,
чтобы избежать рисков.
Последнее редактирование: