Ich mag die Sicherheitsstufe von U2F sehr, aber neben der Sicherheit müssen Sie einen Wiederherstellungsplan in Betracht ziehen. Der Verlust des Zugriffs auf Ihre wichtigsten Konten, wenn mit dem Haupt-U2F-Token etwas passiert, ist ein ernstes Problem. Gleichzeitig möchte ich vermeiden, ein Backup zu verwenden, das die von U2F bereitgestellte Sicherheit gefährdet.
Beliebte Sicherungsmethoden
Bisher war es eine gute Praxis, ein zweites unabhängiges U2F-Token für die Sicherung aufzubewahren. Dieses Token muss manuell zu jedem Dienst hinzugefügt und an einem "sicheren" Ort gespeichert werden. Eine andere gängige Praxis ist die Verwendung der Nicht-U2F-Methode als Backup (OTP, Wiederherstellungscodes). Ehrlich gesagt lassen beide Methoden zu wünschen übrig.
Unabhängiges U2F-Token
Dies bedeutet, dass ich jedes Mal, wenn ich mich bei einem neuen Dienst anmelde, meine beiden Token hinzufügen muss. Diese Tatsache wirft eine Reihe von Problemen auf:
- Ein Backup-Token sollte ziemlich leicht zugänglich sein. Trotz der Tatsache, dass ich es nicht an einem Schlüsselbund mitnehmen werde, sollte ich in der Lage sein, schnell darauf zuzugreifen, sodass ich mir kaum etwas Besseres einfallen lassen kann, als es zu Hause zu behalten. Wie real es ist, selbst wenn ein Safe benutzt wird, können Sie lange sprechen;
- Wenn ich mich unterwegs für einen Dienst registrieren muss, kann ich kein Backup-Token hinzufügen. Sie müssen also versuchen, sich daran zu erinnern, dass Sie es später hinzufügen müssen. Bis dies geschieht, gibt es keine Sicherung. Im schlimmsten Fall kann ich ihn völlig vergessen;
- Wenn ich zu Hause bin, befinden sich meine beiden Token am selben Ort. Diese Sicherungsmethode ist alles andere als ideal: Beide Token sind möglicherweise aufgrund eines Vorfalls nicht verfügbar (zerstört oder gestohlen).
- Die Tatsache, dass das Backup-Token zu Hause gespeichert ist, liegt auf der Hand. Wenn jemand wirklich zu meinem Token kommen möchte, weiß er bereits, wo er danach suchen muss.
- Nicht universelle Methode: Nicht bei allen Diensten können Sie Ihrem Konto mehr als einen Schlüssel hinzufügen.
Meiner Meinung nach ist diese „beispielhafte Praxis“ nicht sehr zuverlässig und ziemlich belastend. Schauen wir uns eine andere gängige Praxis an.
Nicht-U2F-Methode als Backup
OTP:
- Die Verwendung von OTP als Backup ist besser als die Verwendung als Hauptmethode von 2FA, aber die Tatsache, dass OTP vorhanden ist, eröffnet irgendwie einen zusätzlichen Angriffsvektor.
- Telefone fallen aus, gehen verloren und werden gestohlen. Wenn nach dem Verlust die Möglichkeit besteht, dass sie in die Hände von Fremden gelangen, müssen Sie diese Sicherung auf allen Konten manuell abrufen.
- Ich habe immer ein Telefon und ein U2F-Token bei mir, daher ist eine solche Sicherungsmethode alles andere als ideal: Die Wahrscheinlichkeit, beide sofort zu verlieren, ist viel höher als wenn die Sicherung separat gespeichert würde. Dieser Punkt kann jedoch leicht kompensiert werden, indem beispielsweise Authy verwendet wird, das die verschlüsselte Sicherung auf seinem Server speichert.
- Nicht universelle Methode: Leider gibt es eine ausreichende Anzahl von Diensten, die nur benutzerdefinierte Anwendungen anbieten und Standard-TOTP nicht unterstützen.
Wiederherstellungscodes:
- Wiederherstellungscodes müssen an einem sicheren Ort aufbewahrt werden. Auch dieser „sichere Ort“ wird höchstwahrscheinlich mein Zuhause sein, mit fast den gleichen Problemen wie ein separater U2F-Token.
- Wieder eine nicht universelle Methode: Jeder Dienst hat seinen eigenen Ansatz für die Sicherung
Zusammenfassend sind alle diese Methoden nicht universell, belastend und nicht zu sicher.
Die beste Sicherungsmethode
Nachdem ich den aktuellen Stand ausreichend kritisiert habe, werde ich endlich sagen, was ich wirklich will. Ich möchte wirklich zwei U2F-Token haben: Primär- und Backup-Token, aber sie müssen auf eine bestimmte Weise konfiguriert werden:
- Wenn ich das Haupttoken auf einem Gerät registriere, wird das Sicherungstoken für diesen Dienst automatisch betriebsbereit.
- Sobald ich für einen Dienst ein Sicherungstoken verwende, ist das Haupttoken für diesen Dienst ungültig.
Bevor wir die technische Machbarkeit in U2F diskutieren, werde ich erklären, warum es großartig ist und wie ich es verwende.
Warum ist es toll?
Wenn wir uns die Kritik an dem oben beschriebenen unabhängigen Backup-Token ansehen, können wir sehen, dass alle Mängel dieser Methode beseitigt sind:
- Das Backup-Token sollte nicht mehr leicht zugänglich sein. Extreme Beispiele können sein: Ziegelstein in einer Mauer oder anderthalb Meter in einem Garten oder anderswo. Kein Scherz, ich bin ziemlich bereit dafür;
- Unabhängig davon, wo ich mich befinde, muss ich nichts tun, um diesem Dienst ein Sicherungstoken hinzuzufügen, wenn ich mich für einen Dienst anmelde. Ich benutze nur mein Haupt-Token und bin beruhigt, weil ich weiß, dass ich ein Backup habe.
- Für Außenstehende ist völlig unklar, wo sich mein Backup-Token befindet. Selbst wenn man weiß, dass es existiert, macht es kaum Sinn, es selbst zu finden.
- Es ist sicher genug. Selbst wenn meinem Haupttoken etwas Schlimmes passiert, ist es sehr unwahrscheinlich, dass derselbe Vorfall das Sicherungstoken beeinflusst.
- Es ist universell. Diese Sicherungsmethode funktioniert für alle Dienste, die U2F unterstützen, unabhängig davon, was dieser Dienst sonst noch unterstützt.
Und wenn mit dem Haupt-Token wirklich etwas Schlimmes passiert, mache ich Folgendes:
- Ich grabe ein Backup-Token aus / unklar;
- Authentifizieren Sie sich bei allen meinen Diensten mit U2F und löschen Sie dabei das Haupttoken.
- Ich bestelle ein neues Paar Token und füge nach Erhalt allen Diensten ein neues Haupt-Token hinzu und widerrufe das alte.
Zumindest für mich persönlich ist diese Strategie ein großartiger Kompromiss für ein hohes Maß an Sicherheit und eine einfache Sicherungslast. Es ist sicherer und zuverlässiger als jede andere Methode.
Implementierung
U2F-Protokollübersicht
Bevor wir über die Implementierung sprechen können, müssen wir auf einer bestimmten Ebene verstehen, wie U2F funktioniert. Die meisten Hersteller implementieren es wie folgt (nicht alle der folgenden Elemente sind im Standard enthalten; einige Dinge sind Implementierungsdetails, aber die meisten vorhandenen Implementierungen funktionieren meines Wissens genau so):
device_secret
im U2F-Token zusammen mit einem 32-Bit-
counter
programmiert, der nur inkrementiert werden kann. Wenn wir ein U2F-Token für einen Dienst registrieren, geschieht Folgendes:
- Der Browser sendet die
AppID
(tatsächlich den Domänennamen) an das U2F-Gerät. - Das Gerät generiert eine Zufallszahl (
nonce
), kombiniert sie mit der AppID
, leitet sie mithilfe von device_secret
als Schlüssel durch HMAC-SHA256 und der resultierende Hash wird zum privaten Schlüssel für diesen bestimmten Dienst: service_private_key
; - Aus
service_private_key
wird der öffentliche Schlüssel service_public_key
generiert. - Das Gerät nimmt die
AppID
erneut, kombiniert sie mit service_private_key
und leitet sie erneut mit device_secret
als Schlüssel durch den HMAC-SHA256. Das Ergebnis ( MAC
) wird zusammen mit der zuvor generierten nonce
zu key_handle
. - Das Gerät sendet
key_handle
und service_public_key
zurück an den Browser, und der Browser leitet an den Dienst weiter, der diese Daten für zukünftige Authentifizierungen speichert.
Die nachfolgende Authentifizierung erfolgt wie folgt:
- Der Dienst generiert eine
challenge
(zufällig generierte Daten) und sendet sie zusammen mit key_handle
(bestehend aus nonce
und MAC
) an den Browser. Der Browser übergibt dies alles zusammen mit der AppID
(d. H. AppID
Domänennamen) an das Gerät. - Das Gerät mit
nonce
und AppID
generiert service_private_key
auf dieselbe Weise, wie es bei der Registrierung generiert wurde. - Das Gerät generiert einen
MAC
auf die gleiche Weise wie bei der Registrierung. Durch den Vergleich mit dem vom Browser empfangenen MAC
nonce
sichergestellt, dass nonce
nicht ersetzt wird. Daher ist service_private_key
zuverlässig. - Das Gerät erhöht den
counter
. - Das Gerät signiert die
AppID
, AppID
und den counter
mit service_private_key
und sendet die resultierende Signatur ( signature
) und den counter
Browser, der diese Daten weiter an den Dienst überträgt. - Der Dienst überprüft die
signature
mit dem service_public_key
, den er nach der Registrierung hat. Außerdem überprüfen die meisten Dienste, ob der counter
größer als der vorherige Wert ist (wenn dies nicht die erste Authentifizierung ist). Der Zweck dieses Tests besteht darin, das Klonen von U2F-Geräten unzugänglich zu machen. Wenn die signature
übereinstimmt und der counter
größer als der vorherige Wert ist, wird die Authentifizierung als erfolgreich abgeschlossen betrachtet, und der Dienst speichert den neuen counter
.
Lassen Sie uns nun die Details skizzieren, die in direktem Zusammenhang mit der Diskussion stehen.
Details von Interesse
Das erste ist, dass das Gerät nicht für jeden Dienst
service_private_key
speichert,
service_private_key
jedes Mal mit HMAC-SHA256
service_private_key
anzeigt. Dies ist für uns sehr wichtig: Es ist offensichtlich, dass, wenn jedes Gerät eindeutige Schlüssel für jeden Dienst separat speichern würde, sich nur dieses Gerät anschließend authentifizieren könnte.
Dies ist übrigens keine Anforderung von U2F: U2F gibt nicht an, wie Schlüssel gespeichert werden sollen, und einige frühe Implementierungen von U2F haben tatsächlich Schlüssel für jeden Dienst separat gespeichert. Dieser Ansatz hat den Nachteil, dass die Anzahl der Dienste, für die das Gerät verwendet werden kann, begrenzt ist. Die Ableitung von service_private_key
beseitigt diesen Nachteil.Und zweitens verfügt das Gerät über einen
counter
, um das Klonen zu verhindern.
Auf den ersten Blick scheint es, dass dieser
counter
es uns nicht erlaubt, die diskutierte Sicherungsstrategie umzusetzen (zumindest schien es mir, als ich versuchte, eine Lösung zu finden), aber tatsächlich hilft er uns nur! Ich werde es jetzt erklären.
Hauptidee
Die Idee ist folgende: Programmieren Sie in der Produktionsphase zwei Token so, dass beide dasselbe
device_secret
, aber das Backup-Token muss korrigiert werden: Anstatt den
counter
in seiner reinen Form zu verwenden (wie es normale Token tun), sollte es hinzugefügt werden eine große Konstante zu
counter
. Zum Beispiel die Hälfte des 32-Bit-Bereichs, d.h. ungefähr
2 000 000 000
, es sieht vernünftig aus: Es ist unwahrscheinlich, dass ich in meinem ganzen Leben so viele Authentifizierungen erschöpfen werde.
Das ist alles. Einfach und effektiv.
Nachdem zwei Token auf diese Weise programmiert wurden, verstecke ich das Backup-Token an einem
wirklich schwer erreichbaren Ort und berühre es nie. Wenn etwas Schreckliches passiert und ich den Zugriff auf das Haupttoken verliere, komme ich immer noch zum Sicherungstoken und kann es sofort für alle Dienste verwenden, bei denen ich das Haupttoken registriert habe, weil Das Backup hat das gleiche
device_secret
und sein
counter
beginnt mit einer wirklich großen Zahl, die ich für den Rest meines Lebens nicht bekomme.
Ich mache auch darauf aufmerksam, dass
ich nicht vorschlage, Token geklont zu machen . Zwei Token haben, obwohl sie dasselbe
device_secret
haben, unterschiedliche Zähler, und nach dem Programmieren von
device_secret
sollte es keine Möglichkeit geben, sie vom Gerät zurückzubekommen oder auf andere Weise einen Klon zu erstellen.
Ein Hinweis zum Zähler
Ein aufmerksamer Leser kann feststellen, dass das folgende Sicherheitsproblem vorliegt: Was passiert, wenn ein Angreifer Zugriff auf das Haupttoken erhält und auf irgendeine Weise 2.000.000.000 Authentifizierungen initiiert? Dann erhält er Zugriff auf den Dienst, auch nachdem das Sicherungstoken für diesen Dienst verwendet wurde.
Glücklicherweise hat dieses Problem eine einfache Lösung. In jedem Fall muss der Zähler in Hardware implementiert sein (vermutlich auf einem Kryptoprozessor), und für eine sichere Implementierung muss dieser Hardwarezähler einen Bereich von weniger als 32 Bit haben. Beim
ATECC508A können Zähler beispielsweise nur bis 2097151 zählen. Wenn Sie also die dem Zähler hinzugefügte Konstante auf einen Wert setzen, der größer als der Maximalwert des Zählers ist, können Sie sicher sein, dass das Haupttoken niemals zum Zähler im Sicherungstoken zählen kann.
Zur Verdeutlichung: Nehmen wir an, unser U2F-Token verwendet ATECC508A und bezeichnet den Zähler im ATECC508A als
hw_counter
. Dann:
- Im
hw_counter
wir für Berechnungen: hw_counter
; - Im Backup-Token verwenden wir für Berechnungen:
hw_counter + 2000000000
.
Bitte beachten Sie, dass wir den echten
hw_counter
im
hw_counter
nicht ändern. es zählt immer noch von 0 bis 2097151. Stattdessen lesen wir jedes Mal, wenn wir den
hw_counter
müssen,
hw_counter
von ATECC508A, addieren dann unsere Konstante und geben sie zurück (für weitere Berechnungen für U2F).
Somit beträgt der Bereich der Zählerwerte im Haupttoken [0, 2097151], während der Bereich der Zählerwerte im Sicherungstoken [2000000000, 2002097151] beträgt. Die Tatsache, dass sich diese Bereiche nicht überschneiden, stellt sicher, dass das Haupttoken bei Verwendung der Sicherung gelöscht wird (wenn der Dienst einen
counter
; die von mir überprüften Hauptdienste verwenden ihn).
Tatsächliche Umsetzung
Keiner der mir bekannten Hersteller von U2F-Token unterstützt heute die erforderliche Anpassung. Glücklicherweise gibt es eine Open-Source-Implementierung des U2F-Tokens:
SoloKeys .
Ich habe meinen ursprünglichen Artikel (auf Englisch) vor einem Jahr geschrieben, und dieser Teil ist etwas veraltet: Dann befand sich SoloKeys im Prototyping-Stadium und ich habe die vorherige Iteration des Projekts verwendet:
u2f-zero . Daher werde ich diesen Teil jetzt nicht übersetzen, da der einzige Weg, ein u2f-zero-Gerät zu erhalten, darin besteht, es selbst zu löten, und es ist kaum ratsam, dies zu tun (obwohl es Anweisungen auf dem Github gibt).
Trotzdem sind alle Details der notwendigen Modifikation von u2f-zero im
Originalartikel angegeben .
Wenn meine Hände die Solokeys erreichen, schreibe ich Anweisungen für deren Änderung.
Auf die eine oder andere Weise ist dies die einzige Möglichkeit, die ich heute kenne, um ein funktionierendes U2F-Token mit einer zuverlässigen Sicherung zu erhalten. Das Überprüfen mehrerer Dienste (mindestens Google und Github) hat gezeigt, dass dies funktioniert: Durch Registrieren des Haupttokens im Dienst können wir auch die Sicherung verwenden, und nach der ersten Verwendung der Sicherung funktioniert das Haupttoken nicht mehr. Awwwwwww. <3
Warnung
Trotz der Tatsache, dass diese Backup-Strategie cool ist, bin ich mir ihrer spezifischen Implementierung durch u2f-zero oder solokey nicht so sicher. Dieser Weg ist der einzige Weg, um das zu bekommen, was Sie wollen, also bin ich diesen Weg gegangen; Unter der Annahme, dass der Angreifer physischen Zugriff auf das U2F-Gerät erhält, bin ich mir nicht sicher, ob das Hacken des Geräts (d.
device_secret
das
device_secret
von
device_secret
) so schwierig sein wird wie bei Yubikey oder anderen großen Herstellern. Die Autoren von solokey behaupten, dass „das Sicherheitsniveau das gleiche ist wie bei einem modernen Autoschlüssel“, aber ich habe keine Untersuchungen durchgeführt, um dies zu bestätigen.
Um ehrlich zu sein, mache ich mir darüber jedoch keine großen Sorgen. Wenn ein Angreifer einfach einen Token stiehlt, ohne ihn zurückgeben zu wollen, spielt die Komplexität des Brechens keine Rolle, weil Ein Angreifer kann dieses Token einfach verwenden, um auf ein Konto zuzugreifen, und beispielsweise dieses Token einfach widerrufen und ein weiteres hinzufügen. Dafür muss ich jedoch auch andere ernsthafte Sicherheitsprobleme haben. U2F-Token ist nur der zweite Faktor.
Das einzige Szenario, in dem Solokey möglicherweise weniger sicher ist als etwas anderes, ist, wenn ein Angreifer versucht, für einen kurzen Zeitraum auf das Gerät zuzugreifen,
device_secret
von ihm
device_secret
und das Gerät unsichtbar an mich zurückzugeben. Dazu muss er den Inhalt des Flash-Mikrocontrollers (oder des RAM zum richtigen Zeitpunkt) lesen, was nicht sehr trivial ist.
Unter Berücksichtigung aller Faktoren glaube ich, dass eine zuverlässige Sicherung für mich persönlich viel wichtiger ist als eine hochsichere Hardware-Implementierung eines U2F-Geräts. Die Wahrscheinlichkeit von Problemen mit einer solchen sicheren Implementierung und das Fehlen einer guten Sicherung ist höher als die Wahrscheinlichkeit von Problemen mit u2f-zero (solokey) und Sicherung.
Fazit
Die in Betracht gezogene Sicherungsstrategie übertrifft die Alternativen in allen Dimensionen: Sie ist universell, sicherer und zuverlässiger als alle anderen Methoden.
Ich würde mich freuen, wenn mindestens einer der Haupthersteller dies in seinen Produkten umsetzt, aber es gibt noch keine Gewissheit. Ein Mitarbeiter von Yubico, James A., sagte mir sogar, dass die Implementierung des Backups nach Bedarf mit der Art und Weise, wie U2F entworfen wurde, nicht möglich sei. Nachdem ich die Implementierungsdetails dargelegt hatte, reagierte es einfach nicht mehr.
Zum Glück war dies nicht so unmöglich, wie Yubico glaubt.
Mein Originalartikel auf Englisch: Zuverlässige, sichere und universelle Sicherung für U2F-Token . Weil Der Autor des Originalartikels bin ich selbst. Mit Ihrer Erlaubnis habe ich diesen Artikel nicht in die Kategorie „Übersetzung“ eingeordnet .