LUKS Header auf USB-Stick verschieben (für Debian Jessie): Unterschied zwischen den Versionen

Aus codecivil
Zur Navigation springen Zur Suche springen
Zeile 135: Zeile 135:
 
==== Entfernung der Sicherungskopie des Headers ====
 
==== Entfernung der Sicherungskopie des Headers ====
 
Bootet der Rechner wie gewünscht, so sollte die Sicherungskopie entfernt werden.
 
Bootet der Rechner wie gewünscht, so sollte die Sicherungskopie entfernt werden.
<nowiki>
+
<nowiki>
 
rm -f /boot/header
 
rm -f /boot/header
 
  </nowiki>
 
  </nowiki>

Version vom 29. März 2016, 14:48 Uhr

Ausgangssituation und Ziel

Wir gehen davon aus, dass Sie eine LUKS verschlüsselte Festplatte haben, deren Header Sie entfernen und stattdessen von einem USB Stick aus benutzen wollen. Für Geräte, die erst nach dem Bootprozess entschlüsselt werden, ist dies im Allgemeinen kein Problem. Soll dagegen von dem Gerät gebootet werden, ist der Vorgang etwas komplizierter und wird hier beschrieben.

FAQ

Wozu sollte ich den Header von der Festplatte entfernen?

LUKS-verschlüsselte Partitionen sind schwer zu knacken, sofern man keine Konfigurationsfehler begangen hat. Jedoch benötigt jede LUKS-Partition einen Header, in dem steht, wie genau verschlüsselt wird und wo die verschlüsselten Daten beginnen. Dieser Header ist natürlich unverschlüsselt. Selbst mit den Informationen des Headers ist eine Entschlüsselung jedoch sehr aufwendig. Aber: Seine Existenz verrät, dass verschlüsselte Daten vorliegen; und mit einem erpressten Passwort oder Schlüsselfile werden diese Daten zugänglich. Ist der Header (sowie Boot-Partition und Bootloader) aber nicht auf dem Gerät zu finden, das verschlüsselt worden ist, so sind seine Inalte nicht mehr von zufälligen Daten zu unterscheiden und eine Verschlüsselung kann abgestritten werden. Zudem benötigt ein Angreifer nun das Passwort/Schlüsselfile und den Header, man hat also nebenbei eine wirksame Zwei-Faktor-Authentifizierung eingerichtet.

Ist das nicht unsicherer, wenn ich den Header unverschlüsselt mit mir herumtrage?

Der Header ist auch auf der Festplatte schon unverschlüsselt und kann direkt ausgelesen werden, sobald man physischen Zugriff auf das Gerät hat. Auf dem Header ist aber der eigentliche Schlüssel nur verschlüsselt abgelegt; verschlüsselt mit dem Passwort oder Schlüsselfile, das man angelegt hat. Um die Daten auf dem Gerät zu entziffern, muss ein Angreifer nun also den USB Stick und den Rechner in die Hände bekommen. Zwei Arten und Unsicherheit treten aber in der Tat neu auf:

  • Erhält jemand den USB Stick, so kann er in Ruhe eine Brute-Force-Attacke gegen den Master Key auf dem Header fahren. Hat er den geknackt und bekommt nun physischen Zugriff auf das verschlüsselte Gerät, so sind dessen Daten sofort entziffert. Der Master Key lässt sich nur durch eine komplette Neuverschlüsselung ändern, so dass ein Verlust des USB Sticks großen Sicherungsaufwand bedeutet.
  • Files auf einem USB-Stick sind volatiler und die Gefahr einer unabsichtlichen Zerstörung des Headers größer als zuvor. Um dem zu begegnen, schreiben wir den Header nicht als Datei oder in die initramfs auf den Stick, sondern in einen unpartitionierten Bereich. Dort kann nur absichtlich geschrieben oder gelesen werden. Wie zuvor aber auch, ist es empfehlenswert, ein Backup des Headers zu haben.

Warum kann ich nicht einfach die header option in der crypttab benutzen?

Debian Jessie benutzt beim Booten nicht die normale cryptsetup-Binary, sondern "systemd-cryptsetup", eine Version, die im Bootvorgang sicherer sein soll. Momentan ist die Übergabe der "header="-Option dafür nicht implementiert. Wir laden deshalb die später benutzte cryptsetup-Binary nach und benutzen sie mit der Header-Option während der intitramfs-Phase.

Was genau ist unsere Strategie?

Unsere Vorgensweise ist inspiriert von https://wiki.ubuntuusers.de/System_verschl%C3%Bcsseln/Entschl%C3%Bcsseln_mit_einem_USB-Schl%C3%Bcssel. Dort wird beschrieben, wie man einen USB-Stick als LUKS-Schlüssel einrichtet.

Wir schreiben ein Shellskript, das für die Entschlüsselung unter Benutzung des entfernten Headers sorgt. Die Disk-Entschlüsselung startet mit dem Aufruf von cryptroot. Dies geschieht als letztes Script im Ordner /usr/share/initramfs-tools/scripts/local-top. Um dem zuvor zu kommen, legen wir unser Shellskript in diesen Ordner. Über einen Hook sorgen wir dafür, dass dem Shellskript die normalen cryptsetup und vgchange zur Verfügung stehen.

Das Shellskript lädt eine Konfigurationsdatei, die dem Skript sagt, wo der Header auf dem Stick zu finden ist - in einem unpartitionierten Bereich des Sticks - und lädt ihn in das temporäre Filesystem der initramfs. Dort wird er zum Entschlüsseln benutzt. Im Kontrast dazu, den Header direkt in das initrd.img-File zu schreiben, hat das die Vorteile, dass der Header nicht auf dem Filesystem vorgehalten werden muss (weder in der Bootpartition noch in den verschlüsselten Partitionen), um Kernel-Updates reibungslos zu erlauben. Der Header wird nur kurz während des Bootvorgangs in den RAM des Rechners geladen und ist ansonsten nirgends auf dem Filesystem zu finden.

Die Anleitung Schritt für Schritt

Wir gehen im Folgenden davon aus, dass die verschlüsselte Partition /dev/sda5 ist und der USB Stick unter /dev/sdb zu finden ist. Bitte passen Sie die unten folgenden Schritte Ihrer Situation entsprechend an. Für alle Schritte benötigen Sie Administratorrechte. Gegebenenfalls müssen Sie daher sudo vor die entsprechenden Befehle schreiben. Um herauszufinden, wie die Gerätedateien tatsächlich heißen, kann man den Befehl lsblk benutzen. LUKS-entschlüsselte Geräte sind die Eltern der Geräte vom Typ crypt.

Dateien kopieren

Sie benötigen die folgenden drei Dateien:

Kopieren Sie bitte die Linkinhalte in Files mit dem angegebenen Namen.

Verzeichnisse vorbereiten

Wir legen das Verzeichnis an, das unsere Bootkonfiguration ergänzen soll.

mkdir /etc/remoteheader

Vorbereitung des USB Sticks

Wir exportieren zunächst den Header

cryptsetup luksHeaderBackup /dev/sda5 --header-backup-file /etc/remoteheader/header

und sehen uns an, wieviel Platz wir dafür benötigen:

ls -l /etc/remoteheader

Meistens sind dies zwischen zwei und drei Megabyte. Nun müssen wir dafür sorgen, dass auf dem USB-Stick mindestens so viel unpartitionierter Platz zur Verfügung steht. Dazu kann man jedes Partitionierungsprogramm verwenden, am sichersten aber erscheint uns gparted:

gparted /dev/sdb

Falls gparted nicht zur Verfügung steht, kann es mittels

apt-get install gparted

nachinstalliert werden. Mittels fdisk kontrollieren wir nun das Ergebnis:

fdisk -l /dev/sdb

Das kann dann zum Beispiel so aussehen:

Disk /dev/sdb: 7.4 GiB, 7902068736 bytes, 15433728 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x000178bc

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdb1  *       62 15294407 15294346  7.3G 83 Linux
 

In diesem Fall haben wir vor der Partition /dev/sdb1 62 und danach 15433728-15294407=139321 Blöcke von jeweils 512 Bytes zur Verfügung. Vor die Partition passt der Header also nicht, dahinter aber haben wir große Auswahl. Wir könnten zum Beispiel bei Block 15300000 mit dem Header beginnen. Um das zu tun, benutzen wir dd:

dd if=/etc/remoteheader/header of=/dev/sdb bs=512 seek=15300000

Passen Sie bei der Benutzung von dd besonders auf: Fehler können im Allgemeinen nicht rückgängig gemacht werden und eine falsche Gerätedatei kann verheerende Folgen haben.

Sicherung des Headers

Für den Fall, dass etwas schief läuft, sollten wir eine weitere Kopie des Headers in der Boot-Partition haben.

cp /etc/remoteheader/header /boot/header

Editieren von remoteheader.conf

Um die Datei remoteheader.conf anzupassen, benötigen wir folgende Informationen:

  • Die ID des USB Sticks. Diese dient dazu, dass der Header nur von diesem speziellen USB-Stick gelesen wird. Eine Byte-für-Byte-Kopie des USB-Sticks würde nicht funktionieren. Die ID des Sticks findet man so heraus:
ls -l /dev/disk/by-id

Es ist die ID, die zum Gerät /dev/sdb verlinkt. Sie ist meist von der Form "usb-....-0:0". Wir schreiben sie in Anführungszeichen hinter

REMOTEHEADER_DISKID=
  • Den Gerätenamen, vor und nach der Entschlüsselung. Hier haben wir angenommen, dass der erste /dev/sda5 heißt und Debian nennt dann das entschlüsselte Gerät sda5_crypt, sofern man keine andere Angaben macht. Dies sind die Default-Einstellungen
REMOTEHEADER_DEVICENAME_ENCRYPTED="/dev/sda5"
REMOTEHEADER_DEVICENAME_DECRYPTED="sda5_crypt"
 

und müssen bei Bedarf angepasst werden. Wir hätten diese Information auch aus der crypttab lesen können, aber da das Skript kein vollständiges crypttab-Parsing durchführt, wäre dies Augenwischerei.

  • Die Blockgröße des Geräts, meist 512. Sie ist in der Ausgabe des obigen fdisk-Befehls zu finden und wir tragen sie als
REMOTEHEADER_BLOCKSIZE=

ein.

  • Der Startblock des Headers auf dem Stick. Hier haben wir 15300000 gewählt, also wäre
REMOTEHEADER_SKIPBLOCKS="15300000"

einzutragen.

  • Die Länges Headers in Blocks. Ist <HEADERSIZE> die Größe des Heades in Bytes und <BLOCKSIZE> die Blockgröße, so bestimmen wir sie mittels
echo <HEADERSIZE>/<BLOCKSIZE> | bc -l

Dies sollte ganzzahlig sein. Wir tragen den Wert als

REMOTEHEADER_READBLOCKS=

in die Konfigurationsdatei ein.

Verschieben der Dateien

Alle Dateien müssen Root gehören:

chown root:root remoteheader.conf remoteheader.hook remoteheader_script.sh

Die Konfigurationsdatei muss nun in dem neuen /etc-Ordner zu finden und mit minimalen Rechten ausgestattet sein.

cp remoteheader.conf /etc/remoteheader/
chmod 400 /etc/remoteheader/remoteheader.conf 
 

Das Hook-Skript und das Boot-Skript müssen ausführbar sein und in die richtigen Verzeichnisse:

chmod 755 remoteheader.hook remoteheader_script.sh
cp remoteheader.hook /etc/initramfs-tools/hooks/
cp remoteheader_script.sh /usr/share/initramfs-tools/scripts/
 

Update der initramfs

Um den laufenden Kernel herauszufinden, benutzen Sie

uname -r
 

und um den entsprechenden Kernel zu aktualisieren, können Sie einfach

update-initramfs -k $(uname -r) -u
 

benutzen, oder hinter -k die gewünschte Kernelversion schreiben. Um alle Kernels zu aktualisieren, schreiben Sie "all" anstatt der Kernelversion. Die einzigen Fehlermeldungen, die hier auftreten dürfen, sind von der Form "Device /dev/sda5 already opened. FAILED to decrypt using ...". Treten weitere Fehler auf, sollten Sie hier aufhören und auf Fehlersuche gehen. Erst, wenn dieser Schritt erfolgreich war, fahren Sie mit dem nächsten fort.

Entfernung des Headers von der Festplatte und Reboot

Wir überschreiben den Header mit (quasi-)zufälligen Daten:

head -c <HEADERSIZE> /dev/urandom > /dev/sda5; sync
 

Die heruntergeladenen Dateien sollten nun entfernt werden.

rm -f remoteheader.conf remoteheader.hook remoteheader_script.sh
 

Das System kann nun neu gebootet werden.

Entfernung der Sicherungskopie des Headers

Bootet der Rechner wie gewünscht, so sollte die Sicherungskopie entfernt werden.

rm -f /boot/header
 

Troubleshooting

Wiederherstellung des Headers

Um den Header wieder auf sda5 zu schreiben, hat cryptsetup einen eigenen Befehl:

cryptsetup luksHeaderRestore /dev/sda5 --header-backup-file /boot/header

Da der Header vollständig entfernt, muss der Vorgang mit YES bestätigt werden. Jeder nicht-aktualisierte Kernel sollte nun wieder booten. Die aktualsierten Kernel booten, wenn der USB-Stick mit dem Header nicht eingesteckt ist.