Blog

Zwei-Faktor-Authentifizierung und wie man sie implementiert

Authentifizierung ist eines der Hauptprobleme der IT, seit es die Mehrbenutzerfähigkeit gibt. Die einfachste und am häufigsten umgesetzte Lösung ist die Authentifizierung mit einem Passwort. Leider hat diese Art der Authentifizierung ein massives Problem: Computer sind sehr gut darin, schwache Passwörter zu erraten und Menschen sind sehr schlecht darin, sich gut Passwörter zu merken. Aus diesem Grund kam man schon früh auf die Idee, etwas Zusätzliches zu verwenden: die Zwei-Faktor-Authentifizierung war geboren.

Was ist eine Zwei-Faktor-Authentifizierung?

Das ist ganz einfach: Es wird nicht nur eine Information abgefragt, sondern zwei. Im einfachsten Fall kommt zur Passwort-Authentifizierung noch eine zusätzliche Abfrage hinzu. Ein verallgemeinertes Beispiel, das jedem bekannt ist, ist die TAN-Liste, die für Überweisungen im Online-Banking eingesetzt wird.

Im Prinzip gibt es folgende Möglichkeiten, einen zweiten (oder gar dritten) Faktor auszuwählen:

  • Something you know: Das wäre beispielsweise das Passwort.
  • Something you have: Ein (Soft-)Token würde in diese Kategorie fallen. Auch Smartcard mit Zertifikaten ist denkbar.
  • Something you are: Hier kommen wir in den Bereich der Biometrie, also Fingerabdruck, Iris-Scan oder ähnliches.

Da wir in unserem Securai Blog vor allem an praktikablen und einfachen Lösungen interessiert sind, werden wir uns für die Zwei-Faktor-Authentifizierung auf „Wissen“ und „Haben“ konzentrieren.

Was sind die Anforderungen an den zweiten Faktor?

Um eine Zwei-Faktor-Authentifizierung sicher zu gestalten, sind ein paar Anforderungen zu erfüllen. Eine der wichtigsten ist dabei, dass die Generierung bzw. Anzeige des zweiten Faktors niemals auf dem Gerät erfolgen sollte, auf dem der Login stattfindet.

Das bedeutet: Läuft die TAN-Applikation auf dem gleichen Handy wie die Banking-App, besteht die Gefahr, dass eine Schadsoftware beide Software-Teile kontrolliert und damit beliebige Überweisungen ausführen kann.

Die zweite wichtige Anforderung ist, dass der zweite Faktor nicht erratbar oder ohne Zusatzwissen berechenbar sein darf. Das bedeutet konkret: Wenn ich einmal eine TAN erlangt habe, darf es keinen Weg geben, die nächste TAN zu berechnen.

Handelt es sich bei dem zweiten Faktor um einen Wert, der eingegeben werden muss, darf es immer nur einen Wert geben, der für den Login genutzt werden kann. Anders ausgedrückt: Unter keinen Umständen dürfen zwei unterschiedliche Werte zu einem erfolgreichen Login führen.

Grundsätzlich ist auch ein Brute-Force-Schutz zu implementieren, sodass nicht beliebig viele Werte durchprobiert werden können. Schafft es ein Angreifer beispielsweise durch Phishing, auf das gültige Passwort zuzugreifen, sind meist nur 6 bis 8 Stellen durchzuprobieren. Das ist mit heutiger Bandbreite durchaus möglich. Mögliche Schutzszenarien können temporäre Account-Lockouts sein oder das Lösen von Captchas bei mehrmaliger Falscheingabe.

Schlägt der Login fehl, weil das Passwort oder der zweite Faktor (als Wert) falsch eingegeben wurde, ist der derzeitige Faktor als ungültig zu markieren und ein neuer zu generieren. Ein Wert darf also immer nur für genau einen Versuch verwendet werden – schlägt dieser fehl, erfolgt eine erneute Generierung.  Eine Alternative hierzu ist, dass ein Faktor nur für einen bestimmten Zeitraum gültig sein darf (z. B. 30 oder 60 Sekunden). Danach wird automatisch ein neuer Faktor errechnet.

Bei einer Smartcard muss zusätzlich die Möglichkeit gegeben werden, dass diese abläuft (z. B. ein Zertifikat) und dass dieses auch gesperrt werden kann (Certificate Revo?cation List (CRL) oder Online Certificate Status Protocol (OCSP)).

Welche Aufgaben sind zu lösen?

Prinzipiell sind zwei große Aufgaben zu lösen. Zum einen muss der zweite Faktor irgendwie erzeugt werden. Zum anderen muss dieser dem Client irgendwie zugänglich gemacht werden. Im Folgenden stellen wir ein paar Möglichkeiten vor, eine Zwei-Faktor-Authentifizierung zu implementieren und beschreiben, wie diese die obigen Aufgaben lösen.

Einfache Möglichkeit: Standards verwenden

Es gibt zwei Standards, die einem die Erzeugung der Token abnehmen können, wobei der eine auf den anderen aufbaut. Beide Standards haben gleich, dass vor der Inbetriebnahme ein Shared Secret ausgetauscht wurde. Dieses Shared Secret kann entweder manuell eingegeben werden oder über einen halbwegs automatisierten Weg auf den OTP-Client übermittelt werden. Der Google Authenticator verwendet beispielsweise einen QR-Code.

HMAC-basiertes One Time Password (HOTP)

HOTP ist in RFC 4226 definiert und basiert auf der Generierung des Einmalpassworts mit Hilfe der HMAC-Funktion, des oben erwähnten Shared-Secrets und eines Counters, wobei dieser auf beiden Seiten (also Client und Server) hochzuzählen ist.

Die Berechnung erfolgt am einfachsten mit einer Bibliothek (siehe Ende des Artikels), läuft aber grundsätzlich wie folgt ab (entnommen aus dem englischsprachigen Wikipedia-Artikel):

K ist das Shared Secret

C ist der Counter

HOTP(K,C) = Truncate(HMAC(K,C)) & 0x7FFFFFF

Die HMAC-Funktion ist definiert in RFC 2104, wobei jede Programmiersprache eine Bibliothek hat, die diese richtig interpretiert. Die UND-Verknüpfung dient dazu, Problemen mit signed integern aus dem Weg zu gehen und Truncate ist eine Funktion, wie der erzeugte HMAC auf 4-Byte heruntergekürzt wird.

Die große Schwierigkeit bei diesem Vorgehen ist, dass der Client und der Server immer den gleichen Counter haben müssen, da sonst die Authentifizierung fehlschlägt. Es muss also ein sicherer Weg gefunden werden, um den Counter wieder zu synchronisieren, was meist in manuellem Support-Aufwand endet.

Time-based One Time Password (TOTP)

Bei einem zeitbasierten Einmalpasswort wird als „Counter“ einfach ein aus der aktuellen Zeit abgeleiteter Wert verwendet. Definiert wurde das in RFC 6238. Der Google Authenticator verwendet beispielsweise dieses Vorgehen – immerhin muss man nicht aufpassen, dass Client und Server den gleichen Counter-Wert haben.

C wird dann wie folgt berechnet, wenn man sich an den Standard halten will. Das hat den Vorteil, dass der Google Authenticator, der als App für Android, iOS und BlackBerry zur Verfügung steht, verwendet werden kann:

C = int ( unix epoch / 30 )

Anschließend wird auch hier wieder eine Truncate-Funktion aufgerufen und der Wert dann berechnet. Unter https://rcoh.me/posts/two-factor-auth/ ist eine wunderschöne Beschreibung mit Python-Code, wie der Google Authenticator Code berechnet wird. Wer das einfach nur einsetzen will, sei auf die Bibliotheken im Anhang verwiesen.

Eigene Token generieren

Eine andere Möglichkeit, eine Zwei-Faktor-Authentifizierung in die eigene Anwendung einzubauen, ist es, eigene Token zu verwenden. In diesem Szenario wird das Token serverseitig erzeugt und an den Client übermittelt.

Man spart sich dadurch den Austausch des Shared Secrets mit dem Client und sorgt natürlich auch dafür, dass dieses nicht gestohlen werden kann. Der klare Nachteil ist aber, dass das generierte Token bei jeder Authentifizierung an den Client übermittelt werden muss.

Schauen wir uns das Vorgehen genauer an:

Schritt 1: Token generieren

Das ist in diesem Fall tatsächlich relativ einfach. Wir nehmen eine kryptographisch sichere Zufallsfunktion, wandeln diese in eine Ganzzahl um und extrahieren daraus 6 (oder 8) Ziffern – weniger als 6 sollten es nicht sein. Folgender Python-Code zeigt das am einfachsten – es geht natürlich mit jeder anderen Programmiersprache genauso leicht:

token_length = 6                  # Die länge des generierten Tokens, mindestens 6, mehr als 8 ist aber unnötig

random_data = os.urandom(4)       # Wir brauchen 4 Byte kryptographisch sichere Zufallszahlen

random_number = struct.unpack("I", random_data)[0]      # Umwandeln in ein unsigned Integer

token = random_number % 10**token_length                # Wir „kürzen“ das Token mit Module auf die definierte Länge

token_string = str(token).zfill(token_length)           # Falls eine Zahl herauskommt die kürzer ist, mit Nullen auffüllen

Natürlich kann das auch in einer Zeile geschrieben werden, aber es geht ja darum zu verstehen, wie man ein sicheres Einmal-Token erzeugt. Das kann so in jeder anderen Programmiersprache nachgebaut werden. Einzig die Umwandlung der generierten Byte-Folge in eine Zahl könnte etwas nerviger werden (z. B. in Java), aber auch das ist bequem möglich (s. z.B. diesen StackOverflow-Post).

Schritt 2: Token übermitteln

In meinen Augen ist das die größere Herausforderung. Eine sehr einfache Möglichkeit ist der SMS-Versand, wobei dieser natürlich nicht kostenlos ist. Es gibt außerdem Angriffe mit Hilfe des SS7-Protokolls, mit denen SMS ausgelesen werden können.

Eine zweite Möglichkeit ist es, eine eigene App dafür zu schreiben, die mit separaten (!) Zugangsdaten das Token für einen aktuellen Login abfragen kann. Das macht es bedeutend aufwändiger, da nicht nur eine (oder mehrere) zusätzliche App entwickelt werden muss, sondern der Benutzer diese auch installieren muss.

Eine dritte Möglichkeit wäre der Versand per E-Mail, wobei das meist zu langsam und umständlich für den normalen Benutzer ist.

Welches nun das vernünftigste ist, muss man in einer Kosten-Nutzen-Analyse, kombiniert mit einer Risiko-Betrachtung, untersuchen. SMS ist einfacher, kostet aber permanent und kann unter Umständen abgefangen werden, eine eigene App ist sicherer, dafür aber auch bedeutend aufwändiger.

Schritt 3: Token verifizieren

Das ist auch wieder einfach, ich möchte hier nur nochmal auf die Anforderungen an den zweiten Faktor (s. oben) verweisen.

Hardware Token: Zwei-Faktor-Authentifizierung mit dem YubiKey

Ein YubiKey ist ein USB-Stick, der sowohl als Smardcard arbeiten kann als auch eine Zwei-Faktor-Authentifizierung anbietet.

Dabei stellt die dahinterliegende Firma Yubico einen Cloud-Service (YubiCloud) zur Verfügung, der die eigentliche Authentifizierung übernimmt. Es gibt auch offene Authentifizierungsdienste, sodass nicht der Cloud-Service genutzt werden muss. Der Vorteil der Cloud ist: Alle neu ausgerollten YubiKeys können sich von Anfang an an der Cloud per OTP authentifizieren. Die Nutzung der YubiCloud ist auch kostenlos möglich. Es muss nur mit Hilfe einer einfachen Registrierung ein API-Key besorgt werden.

Es gibt vorgefertigte Bibliotheken für Java, .NET, C, Python, PHP und Perl und kann in allen gängigen Anwendungen (auch für Web) verwendet werden. Einzig der Einsatz auf mobilen Endgeräten ohne USB-Port ist nicht ohne weiteres möglich. Es gibt zwar eine NFC-Version davon, allerdings funktioniert das bei iPhones erst ab den 7er Geräten mit iOS11.

Die Authentifizierung läuft dann dahingehend ab, dass der Benutzer den Button auf dem Yubikey betätigt. Je nach Anwendungsszenario wird die Authentifizierung dann direkt ausgelöst oder der Validierungswert in ein Textfeld geschrieben und das Formular (z. B. im Webbrowser) automatisiert abgesendet. Mit Hilfe der YubiCloud wird das Token dann verifiziert. Darüber kann auch eine Authentifizierung komplett ohne Passwort realisiert werden, allerdings würde ich davon nur bei dem Einsatz eines eigenen Authentifizierungsservers Gebrauch machen.

Weitere Details dazu finden sich auf den Entwicklerseiten von Yubico: https://developers.yubico.com/OTP/

FIDO Universal Second Factor (U2F)

Eine andere Möglichkeit ist die Unterstützung des U2F-Verfahrens der FIDO Alliance. Das ist ein Zusammenschluss mehrerer Firmen, die die Zwei-Faktor-Authentifizierung möglichst einfach nutzbar machen wollen.

In nächster Zeit dürfte das tatsächlich ein sehr interessantes Verfahren werden, vor allem im Web-Bereich. Allerdings unterstützt im Moment nur Chrome in der Standardeinstellung U2F – bei Firefox ab Version 57 („Quantum“) ist der Support zwar mit drin, muss aber händisch aktiviert werden. Firefox wird wohl den Weg über die WebAuth API gehen.

Ist das schlau? Smartcard als Zwei-Faktor-Authentifizierung

Eine komplett andere Möglichkeit ist der Einsatz von Smartcards. Der zweite Faktor wird dann mit Hilfe von Zertifikaten umgesetzt, wobei der private Schlüssel auf der Smartcard liegt. Dieses Vorgehen gilt als sehr sicher, ist aber unglaublich aufwändig. Im Prinzip bedeutet dies, dass eine Public-Key-Infrastruktur aufgebaut oder (teuer) eingekauft werden muss, die Leser verteilt und die Smartcards ausgerollt werden müssen. Mit mobilen Anwendungen wird es noch bedeutend schwieriger.

Fazit: Für große Firmen eine gute und sehr sichere Alternative. Für alle anderen sehr aufwändig.

Teure Lösungen: RSA und Co.

Es gibt natürlich noch die bekannten „Platzhirsche“ im Bereich der 2FA. Darunter zählen RSA, ActiveIdentity und weitere.

Da diese jedoch für ein Deployment außerhalb des eigenen Unternehmens nicht praktikabel sind, wollen wir hier auch nicht weiter darauf eingehen.

Fazit

Im Prinzip kommen drei Verfahren in Frage: die OTP-Generierung mit einem Secret, die OTP-Übermittlung an den Client über SMS oder Webservice und der Einsatz eines bezahlbaren und universal einsetzbaren Authentifzierungstokens wie YubiKey.

Die Hardware-Lösung mit YubiKey ist in meinen Augen nur für besonders sensible Anwendungen sinnvoll, da ein Key immer noch im mittleren zweistelligen Euro-Bereich liegt. Er ist zwar universell einsetzbar, das tröstet über die hohen Kosten aber auch nur teilweise hinweg.

Im Bereich der Shared Secrets ist klar das zeitbasierte TOTP-Verfahren vorne, da man sich viel Support für die Synchronisierung spart. Auch gibt es mit dem Google Authenticator Apps als Generatoren für alle relevanten mobilen Plattformen. Wichtig nochmal zur Erinnerung: Eine App zu verwenden und sich auf dem gleichen Smartphone auch anzumelden ist nicht ausreichend sicher. Schließlich ist ja das Ziel, die beiden Kanäle soweit zu trennen, dass selbst wenn ein Teil vollständig kompromittiert ist, der andere noch funktioniert.

Für den Support die einfachste Lösung ist die Übermittlung eines selbst erzeugten, sicheren Tokens per SMS. Das kann jeder empfangen, der ein Mobiltelefon hat und muss nichts installieren. Allerdings kostet der SMS-Versand und es gibt Angriffe, um SMS abzufangen. Eine eigene App ist zwar eine sinnvolle und sichere Alternative, aber das erhöht natürlich den Aufwand für den Benutzer enorm.

Es ist hoffentlich klargeworden, dass es viele und vor allem auch einfache Möglichkeiten gibt, eine Zwei-Faktor-Authentifizierung in die eigene Anwendung zu integrieren. Alle vorgestellten Lösungen haben Vor- und Nachteile, die je nach Einsatzszenario gegeneinander abgewogen werden müssen. Natürlich unterstützen wir Sie gerne im Rahmen einer Beratung zur sicheren Software-Entwicklung!

Bibliotheken:

Vorheriger Beitrag
Schöne Feiertage und einen guten Rutsch!
Nächster Beitrag
IoT Pentest – Der Weg von der Firmware zur Shell

Ähnliche Beiträge

Es wurden keine Ergebnisse gefunden, die deinen Suchkriterien entsprechen.