Bastian Raschke
Nils Tegetmeyer

Sicherheitskritisch

Ein Blog über IT-Sicherheit und Technik

ArduKey - OTP-Generator für Zweifaktor-Authentifizierung (2FA) mit Arduino

Verfasst von Bastian Raschke.
Veröffentlicht am 2015-06-30 in der Kategorie Security.

Zweifaktor-Authentifizierung (2FA) liegt im Trend. Mitverantwortlich sind unter anderem die Yubikeys. Diese handlichen USB-Stick-ähnlichen Geräte werden mittlerweile für viele 2FA-Anwendungen genutzt.

Die Technik hinter den Yubikeys fande ich sehr interessant und ich habe mit dem Projekt "ArduKey" ein vollständig kompatibles Gerät auf Basis der Arduino-Plattform entwickelt, das es ermöglicht, diverse sicherheitskritische Anwendungen (z.B. die Anmeldung an Servern) per 2FA zusätzlich abzusichern. Alle dabei beteiligten Komponenten sind als Open-Source verfügbar und können auf der eigenen Infrastruktur betrieben werden.

Folgend seht ihr das entstandene Endprodukt:

ArduKey - zusammengebaut
Bild: ArduKey in zusammengebauter Form

ArduKey - geöffnet
Bild: ArduKey in komplett zerlegter Form

Vorgeschichte

Als ich zum ersten mal von den Yubikeys gehört habe, war ich direkt begeistert von der Idee dahinter. Auch wenn der grundsätzliche Ansatz (Erzeugung von OTPs mit einem physikalischen Gerät) nicht wirklich neu war, ist die moderne Politik der Firma Yubico und die innovativen Ansätze bei den Produkten ein Grund dafür, warum sie in dem Bereich meiner Meinung nach berechtigt Marktführer sind. Sicherheit wird bei den Produkten tatsächlich groß geschrieben und nicht nur aus PR-Gründen vorgetäuscht. Die Software und die Spezifikationen sind offen und frei zugänglich. Dies hat weltweit viele Entwickler motiviert, weitere Dritt-Software für die Yubikeys zu schreiben und so gibt es in nahezu jedem Bereich eine Anwendung für Yubikeys.

Da auch ich die Technik dahinter wie gesagt sehr interessant finde, und da ich mal wieder große Lust auf ein hardware-nahes Projekt hatte, ist die Idee entstanden, einen eigenen OTP-Generator auf Basis eines Arduino umzusetzen. Zuvor hatte ich noch nicht mit der Arduino-Plattform bzw. AVRs gearbeitet und das ganze Projekt war somit eine große Herausforderung für mich. Weiterhin hat es mich sehr gereizt, anerkannte Kryptografie auf so niedriger Hardware-Ebene mit vergleichsweise leistungsschwachen Embedded-Geräten zu nutzen.

Da der Arduino Leonardo in der Lage ist, Tastatur und Maus zu emulieren, nahm die Idee immer realistischere Formen an. Nachdem ich dann einen Arduino Leonardo im August 2014 erworben hatte, habe ich einige Machbarkeitsstudien durchgeführt (was mit meinen Mitteln möglich ist, und was nicht), um die Projektziele etwas genauer abstecken zu können. Anfänglich hatte ich einige Phasen, in denen ich fast frustriert aufgegeben habe, da einige Bibliotheken nicht wie erwartet funktionieren wollten oder ich mit diversen Arduino (IDE)-Wehwehchen zu schaffen hatte.

Recherche und Umsetzung

Schließlich habe ich aber doch eine schlanke und performante Krypto-Bibliothek für den Arduino gefunden, die mir erfolgreich Daten mit dem AES ver- und entschlüsseln konnte. Und damit war auch schon die kritische Phase überstanden. Die anderen Herausforderungen schienen mir absolut machbar. Schließlich habe ich noch ein sehr interessantes Projekt gefunden, das ein ganz ähnliches Ziel hatte, jedoch meiner Meinung nach recht unübersichtlich, spartanisch dokumentiert und unnötig aufgeblasen ist, weil es direkt die allgemeinen Bibliotheken von Yubikey nutzt, anstatt nur die benötigten Teile zu implementieren. Aber nichtsdestotrotz verdanke ich diesem Projekt einiges an meinem Verständnis, wie ein Yubikey technisch funktioniert.

In den nächsten Monaten habe ich dann recherchiert und nachvollzogen, wie das Konzept der Yubikeys im Detail funktioniert und entsprechende Funktionalitäten neu für einen Arduino/AVR implementiert. Anfänglich habe ich noch ein leicht abgewandeltes OTP-Format verwendet, mich aber schließlich für das gut durchdachte Yubikey-Format entschieden und volle Kompatibilität hergestellt. Die Firmware nahm im Laufe der Zeit immer bessere Formen an und bot immer mehr das, was ich von dem Projekt erwartete.

Hier seht ihr ein Screenshot während ich die ArduKey Firmware entwickelt habe:

ArduKey Firmware - Während der Entwicklung

Planung der Hardware

Ich hatte dabei aber auch immer parallel einen Gedanken an die spätere Hardware im Kopf, da ich das Projekt ja auch produktiv verwenden wollte. Anfänglich wollte ich einen normalen Arduino Nano einsetzen, da dieser kleiner und handlicher als ein Leonardo ist und ebenfalls die Tastatur-Emulation-Features bietet. Jedoch ist ein Nano ja recht teuer und auch formtechnisch nicht wirklich als USB-Stick verwendbar. Deshalb war ich froh, dass ich das TinyUSBBoard-Projekt von Stephan Bärwolf gefunden habe. Dies bot mir eine sehr günstige, Arduino-kompatible Plattform, die passenderweise auch in USB-Stick-Form war. Somit habe ich das Projekt mehr und mehr für das TinyUSBBoard optimiert, ohne aber die Kompatibiltät zu einem normalen Arduino aufzugeben.

Mein Referenzdesign des ArduKey basiert also auf einer stark minimalisierten Version des TinyUSBBoards, die lediglich alles Nötige für den Zweck an Bord hat (keine LEDs und nur einen Schalter):

Ansicht der ArduKey-Platine von oben
Bild: Ansicht der ArduKey-Platine von oben

Ansicht der ArduKey-Platine von unten
Bild: Ansicht der ArduKey-Platine von unten

Entwicklung der Infrastruktur

Damit der ArduKey auch produktiv verwendet werden kann, sind logischerweise noch weitere Komponenten nötig. Es muss einerseits von einer zentralen Stelle geprüft werden können, ob ein OTP gültig ist, und andererseits muss es mindestens eine Anwendung gegen, die OTPs als Zweifaktor-Authentifizierung nutzt.

Diese anderen beiden Komponenten (Auth-Server und PAM-Modul - genauere Erklärung siehe jeweils unten) wurden dann ab November 2014 parallel mitentwickelt. Große Hilfe hatte ich beim Protokollentwurf des Auth-Servers von Nils und bei dem PAM-Modul von Phil. Im Februar 2015 waren alle Komponenten schließlich nahezu fertig für die produktive Verwendung. Und erst jetzt komme ich dazu, alles in diesem Artikel niederzuschreiben, zu dokumentieren und endlich zu veröffentlichen ;-) Weiterhin wurden vor der Veröffentlichung dieses Artikels alle Komponenten noch einmal gründlich durchgetestet und entsprechend verbessert.

Übersicht der Infrastruktur

Die gesamte Infrastruktur besteht aus 3 Komponenten, die ich im folgenden kurz erklären werde.

Zum besseren Überblick schon einmal ein Sequenzdiagramm, wie die Authentisierung eines Benutzers erfolgt:

Sequenzdiagramm der ArduKey-Infrastruktur

Der Benutzer übergibt das OTP, welches er mit einem ArduKey erzeugt hat, an das PAM-Modul, um sich zu authentifizieren. Das PAM-Modul schickt das OTP zur Prüfung an den Auth-Server, welcher dem PAM-Modul dann mitteilt, ob das OTP gültig ist oder nicht. Je nach dem wird der Benutzer dann durch das PAM-Modul authentisiert.

1 - ArduKey USB-Stick

Der eigentliche ArduKey ist der Generator für OTPs und jeder Benutzer der Infrastruktur bekommt ein solches Gerät. Der ArduKey ist betriebssystemunabhängig, da er sich an einem Computer als normale USB-Tastatur anmeldet und das OTP mit einem Druck auf den Knopf "eintippt".

Bevor ihr den ArduKey via der Arduino IDE mit der ArduKey-Firmware bespielen könnt, müsst ihr alle Schritte des TinyUSBBoard-Artikels durchführen. Klont euch dann die ArduKey-Firmware. Nun stellt den "Sketchbook Speicherort" eurer Arduino IDE auf den Ordner src des geklonten Projektes ein.

Arduino IDE Einstellungen - Sketchbook Speicherort
Der Pfad muss bei euch natürlich anders sein

Nach einem Neustart der Arduino IDE sollte unter der Auswahl: "Tools > Boards" auch das "tinyUSBboard (USBaspLoader ATmega8 at 16MHz, Rev.3 and newer)" vorhanden sein, welches ausgewählt wird. Dann könnt ihr den Sketch sketches/Setup/Setup.ino öffnen.

Dieser Sketch hat den einzigen Zweck, die öffentliche Kennung (Public ID), die geheime Kennung (Secret ID) sowie den AES-Schlüssel persistent in den Speicher (EEPROM) des ArduKey zu schreiben. Ihr solltet also unbedingt die geheime Kennung und den AES-Schlüssel verändern, bevor ihr den Sketch auf euren ArduKey schreibt, da die Sicherheit davon abhängt, dass diese Daten geheim bleiben!

Tipp: Ihr könnt diesen [1] kleinen Python-Skript verwenden, um euch zufällige Daten definierter Länge in der korrekten hexadezimalen "Array"-Form ausgeben zu lassen. Mit dem Aufruf "python ./generate-keys.py 16" erhaltet ihr beispielsweise einen zufälligen 16 Byte langen Wert, den ihr dank der passenden Form direkt im Sketch einfügen könnt. Mit dem Aufruf "python ./generate-keys.py 6" erhaltet ihr analog einen Wert, den ihr für die geheime Kennung einsetzen könnt.

Zunächst ändert ihr den AES-Schlüssel:

const uint8_t aesKey[AES_KEYSIZE] =
{
    0x7A, 0x18, 0x58, 0x59, 0x2F, 0xCB, 0x76, 0xBD, 0x5E, 0xB2, 0x68, 0x54, 0x21, 0xAE, 0xD4, 0x5E
};

Dieser ist 16 Byte lang, und kann beliebig geändert werden.

Nun ändert ihr noch die geheime Kennung:

const uint8_t secretId[ARDUKEY_SECRETID_SIZE] =
{
    0xB0, 0xD4, 0xA2, 0xD6, 0x9B, 0xC4
};

Diese ist 6 Byte lang und kann ebenfalls beliebig geändert werden.

Die öffentliche Kennung sollte inkrementell pro ArduKey geändert werden (eine Art Seriennummer), damit die Geräte offensichtlich unterschieden werden können. Es ist aber auch möglich, die Kennung nach Belieben zu ändern, Hauptsache die verwendeten ArduKeys pro Auth-Server haben unterschiedliche Kennungen:

const uint8_t publicId[ARDUKEY_PUBLICID_SIZE] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};

Die öffentliche Kennung ist ebenfalls 6 Byte lang.

Statt eines PROG-Tasters (beim TinyUSBBoard) habe ich bei der ArduKey einen Jumper verbaut, der für das Programmieren gesetzt werden muss. Mit gesetztem Jumper wird der ArduKey also mit dem Computer verbunden, und es kann daraufhin der Sketch auf das Gerät geflasht werden. Nach dem erfolgreichem Flash-Vorgang wird der ArduKey vom Computer getrennt und der Jumper wird entfernt. Nun muss der ArduKey erneut kurz mit dem Computer (oder einer Stromquelle) verbunden werden, damit die eingestellten Parameter persistent in den Speicher (EEPROM) geschrieben werden. Dieser Schritt ist aber wirklich nur nötig, wenn ihr die Parameter initial setzen oder ändern wollt.

Nun wird der ArduKey mit dem richtigen Produktiv-Sketch bespielt. Dazu setzt ihr wieder den Jumper und steckt den ArduKey in den Computer. Dann öffnet ihr den Sketch sketches/Production/Production.ino und flasht diesen wie gehabt mit der Arduino IDE auf das Gerät. Nach erfolgreichem Flash-Vorgang kann der ArduKey entfernt werden (natürlich auch den Jumper entfernen) und ist dann produktiv einsetzbar.

Dies könnt ihr testen, indem ihr den ArduKey an einen Computer ansteckt, einen beliebigen Texteditor öffnet, und den Knopf am ArduKey drückt. Es sollte nun ein OTP "eingetippt" werden:

cccccccccccbjjfrnkigbbufkfckbnfvnvcfklbucugn

Wichtig: Ich habe die Erfahrung gemacht, dass der ArduKey ca. 1-2 Sekunden braucht, bis er korrekte OTPs ausgibt. Drückt ihr zu schnell auf den Knopf, wird kein vollständiges OTP ausgegeben! Ich vermute die Ursache bei der USB-Kommunikation, die dann initial noch nicht korrekt aufgebaut wurde.

Wenn alles grundsätzlich funktioniert hat, ist der ArduKey bereit zur Verwendung.

Alternative: Arduino Leonardo

Wenn ihr keine Zeit oder Lust habt, einen komplettes TinyUSBBoard bzw. ein ArduKey zu bauen, dann könnt ihr die Firmware auch auf einem normalen Arduino Leonardo ausprobieren ohne große Schwierigkeiten. Dazu folgt ihr den obigen Schritten äquivalent bis auf, dass ihr natürlich unter "Tools > Boards" den "Arduino Leonardo" auswählt und die Jumper-/PROG-Taster-Anmerkungen überlest.

Vorher müsst ihr jedoch in der Datei src/libraries/ArduKey/ArduKey.h folgende zwei Zeilen abändern.

Zunächst ändert ihr die Zeile:

#define ARDUKEY_ENABLE_DEFAULT_KEYBOARD_LIBRARY 1

zu

#define ARDUKEY_ENABLE_DEFAULT_KEYBOARD_LIBRARY 0

und daraufhin die Zeile:

#define ARDUKEY_ENABLE_ARDUINO_KEYBOARD_LIBRARY 0

zu

#define ARDUKEY_ENABLE_ARDUINO_KEYBOARD_LIBRARY 1

Nach dem erfolgreichen Flaschen sollte der Arduino Leonardo bei dem Druck auf einen Taster (zwischen Digital 12 und GND) wie gewünscht OTPs ausgeben. Folgend der schematische Aufbau:

Alternativ verwendeter Arduino Leonardo

2 - Authentifizierungsserver

Natürlich muss es in der Infrastruktur auch eine Instanz geben, die die generierten OTPs auf Gültigkeit prüft. Diese Aufgabe übernimmt der Authentifizierungsserver (kurz: Auth-Server), der komplett in Python geschrieben wurde.

Der Auth-Server ist von zentraler Wichtigkeit, da er als Einziger die Geheimnisse (geheime Kennungen, AES-Schlüssel) aller ArduKeys kennt und somit die OTPs entschlüsseln und verifizieren kann. Man sollte sich deshalb im Klaren sein, dass dieser für einen potentiellen Angreifer ein lohnenswertes Ziel ist. Wird in die Maschine des Auth-Servers eingebrochen, ist die Integrität alle verwalteter ArduKeys gefährdet!

Installation

Den Auth-Server könnt ihr bequem über das PM Codeworks-Repository installieren, das wir schon in der Vergangenheit genutzt haben und dessen Einrichtung hier nicht noch einmal erklärt wird.

~# apt-get install ardukey-auth-server

Alternativ könnt ihr auch direkt das Debian-Quellenpaket von Github klonen.

Konfiguration

Die Konfiguration wird in der Datei /etc/ardukey-auth-server.conf vorgenommen und ist schnell abgeschlossen:

Es muss lediglich die IP-Adresse angepasst werden, über die der Server erreichbar ist. Standardmäßig ist der Server nur auf der lokalen Maschine erreichbar (127.0.0.1). Dies solltet ihr ändern, so dass der Auth-Server beispielsweise auch im Intranet oder im Internet erreichbar ist:

server_address = 11.22.33.44

Nach einem Neustart:

~# /etc/init.d/ardukey-auth-server restart

sollte der Server nun entsprechend unter der gegebenen Adresse (standardmäßig auf Port 8080) erreichbar sein:

ArduKey Authentifizierungsserver ist verfügbar

ArduKey hinzufügen

Nun muss der bereits programmierte ArduKey dem Auth-Server bekannt gemacht werden, damit er in der Infrastruktur verwendet werden kann: Der Auth-Server muss also die geheimen Parameter kennen, die wir oben gesetzt haben. Mit dem Programm ardukey-auth-conf (als Root) können ArduKeys auf dem Server verwaltet werden.

Aus Sicherheitsgründen solltet ihr zuvor temporär die History-Protokollierung eurer Shell deaktivieren:

~# unset HISTFILE

Durch folgenden Befehl wird ein ArduKey hinzugefügt:

~# ardukey-auth-conf --add-ardukey cccccccccccb b0d4a2d69bc4 7a1858592fcb76bd5eb2685421aed45e

In diesem Beispiel wurden die Daten des oben programmierten ArduKeys verwendet:

Wert
Öffentliche Kennung cccccccccccb
Geheime Kennung b0d4a2d69bc4
AES-Schlüssel 7a1858592fcb76bd5eb2685421aed45e

Hinweis: Wer nun gut aufgepasst hat, dem wird auffallen sein, dass wir oben die öffentliche Kennung "000000000001" einprogrammiert haben, dem Auth-Server nun aber der Wert "cccccccccccb" gegeben wird. Dies hat den einfachen Grund, dass die "eingetippten" OTPs des ArduKey speziell kodiert sind (sogenanntes Modhex), sodass diese unabhängig von dem Tastatur-Layout des verwendeten Computers immer gleich sind. Ansonsten würde ein OTP auf einem deutschen Computer anders ausgegeben werden als beispielsweise auf einem Französischen.

Ihr bekommt die öffentliche Kennung eines ArduKey in dieser speziellen Darstellungsweise am einfachsten, wenn ihr die ersten 12 Zeichen irgend eines ausgegebenen OTP des ArduKeys kopiert.

API-Key erzeugen

Damit nicht jede x-beliebige Person, die zufällig über die Adresse des Auth-Servers stolpert, Anfragen zur Gültigkeit von OTPs stellen kann, ist dafür ein sogenannter API-Key nötig. Anfragen, die nicht durch einen gültigen API-Key signiert wurden, bearbeitet der Auth-Server grundsätzlich nicht.

Somit brauchen alle Instanzen, die OTPs via dem Auth-Server verifizieren lassen wollen, einen solchen API-Key (jede Instanz sollte einen eigenen API-Key bekommen). Mit folgendem Befehl wird ein neuer API-Key erzeugt:

~# ardukey-auth-conf --generate-apikey

Als Ergebnis wird der neue API-Key angezeigt:

The API key has been generated successfully.
API id:        1
Shared secret: 4NJCNJEQJCAZW58EQKQRO8MI6DDHDRI9HLF2J7LFA8WF5K7HCN1DD9YN1WRJLREU

Der erzeugte API-Key besteht aus zwei Teilen: Die "API id" kann zum einfachen Verständnis als Benutzername gesehen werden und das "Shared secret" als das zugehörige Passwort. Diesen API-Key werden wir später nutzen.

Tipp: Weitere Operationen

Natürlich sind mit dem Programm ardukey-auth-conf noch viele weitere Operationen (z.B. ArduKeys und API-Keys anzeigen, deaktivieren, löschen) möglich, die bei Interesse in der Man-Page nachgelesen werden können.

3 - PAM-Modul

Nun ist durch den Auth-Server und einen oder mehrere ArduKeys die Infrastruktur eigentlich schon funktionsfähig. Allerdings fehlt noch eine Komponente, die diese Infrastruktur auch wirklich nutzt. Generell sind diverse Clients (Linux/Windows-Anmeldung, 2FA-Schutz bei Webseiten, ...) denkbar, die beim Auth-Server abfragen, ob ein eingegebener OTP gültig ist und zu Benutzer X gehört. Wir haben uns für den Linux-Kontext entschieden und ein ArduKey-PAM-Modul entwickelt (vielen Dank an Phil, der große Teile des Moduls mit umgesetzt hat).

Durch PAM-Module ist es ja bekannterweise möglich, eine flexible Schnittstelle zu der generellen Linux-Benutzerauthentifizierung zu nutzen und z.B. Möglichkeiten zur Anmeldung an Linux-Computern zu schaffen. Wir werden im Folgenden die ArduKeys nutzen, um die Linux-Benutzerauthentifizierung mit 2FA zusätzlich abzusichern.

Installation

Das PAM-Modul wird ebenfalls bequem aus dem PM Codeworks-Repository installiert:

~# apt-get install libpam-ardukey

Alternativ könnt ihr auch direkt das Debian-Quellenpaket von Github klonen.

Konfiguration

Die Konfiguration wird in der Datei /etc/pam-ardukey.conf vorgenommen und ist auch hier schnell abgeschlossen.

Zunächst passt ihr die Adresse an, unter die das PAM-Modul den Auth-Server erreichen kann. Falls ihr mehrere Adressen habt, könnt ihr diese, mit Komma getrennt, hintereinander schreiben. Falls der erste Auth-Server bei einer Anfrage mal nicht erreichbar ist (nach Ablauf der bei timeout angegebenen Sekunden), dann wird der zweite kontaktiert (und so weiter). In unserem Fall haben wir aber nur einen Auth-Server:

servers = 11.22.33.44:8080

Nun werden wir noch den bereits erzeugten API-Key eintragen, damit das PAM-Modul mit dem Auth-Server sprechen kann, und die OTPs prüfen lassen kann:

api_id = 1
shared_secret = 4NJCNJEQJCAZW58EQKQRO8MI6DDHDRI9HLF2J7LFA8WF5K7HCN1DD9YN1WRJLREU

Und damit ist die Konfiguration eigentlich auch schon abgeschlossen.

Absicherung von SSH durch 2FA

Nun werden wir aber noch exemplarisch den SSH-Zugang eines entfernten Servers für den Benutzer root absichern, damit selbst bei Kenntnis seines Passworts oder der Kompromittierung seines geheimen Schlüssels kein Zugang möglich ist. Folgende Bilder zeigen den Zustand, wenn alles richtig eingerichtet ist:

SSH geschützt durch 2FA mit ArduKey - vor der Anmeldung
Bild: Nach der erfolgreichen Anmeldung durch einen SSH-Schlüssel wird ein ArduKey OTP gefordert

SSH geschützt durch 2FA mit ArduKey - erfolgreich angemeldet
Bild: Nach der Prüfung des OTP durch den Auth-Server wird der Zugang gewährt

Hinweis: Für folgende Schritte wird der OpenSSH-Server in Version 6.2 oder höher benötigt, da richtige 2FA es erst ab dieser Version möglich ist. Wenn ihr Debian 7 verwendet, könnt ihr den OpenSSH-Server aus den Backports nutzen, bei Debian 8 ist standardmäßig eine korrekte Version verfügbar.

Zunächst wird in der Datei /etc/ssh/sshd_config kontrolliert, ob folgende Einstellung gesetzt sind:

ChallengeResponseAuthentication yes

Weiterhin wird folgender Block am Ende hinzugefügt:

Match Group twofactor
    AuthenticationMethods publickey,keyboard-interactive

Somit wird bei allen Benutzern, die der Gruppe twofactor angehören, neben der SSH-Schlüsselauthentifizierung eine zweite Authentifizierung durch ArduKey nötig. Dieses Konzept erlaubt es, ohne ständige Änderungen der SSH-Server-Konfiguration bei einzelnen Benutzern bequem 2FA zu aktivieren oder deaktivieren (einfach zur Gruppe hinzufügen/entfernen). Nur wenn beide Authentifizierungsarten erfolgreich waren, wird der Benutzer angemeldet.

Natürlich müssen wir die Gruppe aber erst einmal erstellen:

~# addgroup twofactor

Weiterhin erstellen wir ein PAM-Profil für ArduKey:

~# echo "auth sufficient pam_python.so pam_ardukey.py" > /etc/pam.d/ardukey-twofactor

Nun fügen wir folgenden Block über der Zeile @include common-auth in das SSH-PAM-Profil "/etc/pam.d/sshd" ein:

# ArduKey two factor authentication:
@include ardukey-twofactor

Und abschließend starten wir den SSH-Server neu:

~# /etc/init.d/ssh restart

Nun wird noch der Benutzer root mit dem obigen ArduKey verknüft.

Dazu wird das mitgelieferte Programm pam-ardukey-conf genutzt, um die öffentliche Kennung des ArduKey mit dem Benutzer zu verknüpfen (dadurch wird eigentlich nur automatisiert die Datei ~/.pam-ardukey.mapping geschrieben):

~# pam-ardukey-conf --add-user root

Dabei müsst ihr die öffentliche Kennung des ArduKey angeben:

~# pam-ardukey-conf --add-user root
Are you sure you want to assign an ArduKey device to the user "root"? (Y/n) Y
Please enter the public ID of your ArduKey device: cccccccccccb
Successfully assigned the ArduKey device to the user "root"!

Schließlich wird der Benutzer noch der Gruppe twofactor hinzugefügt:

~# adduser root twofactor

Und ab sofort sollte bei der Anmeldung von root als zweites immer ein ArduKey OTP gefordert werden.

Bei allgemeinen Problemen (z.B. wenn die Authentifizierung nicht klappt) kann der Log meist ganz hilfreich sein:

~# grep "pam_ardukey" /var/log/auth.log | tail

Fragen oder Anregungen

Wenn ihre Fragen oder andere Anregungen zu dem Projekt habt, stellt diese einfach per E-Mail. Das Projekt ist durch die drei Komponenten durchaus komplex und ich habe möglicherweise nicht alles ausreichend darstellen können.

Abschließender Hinweis

Es soll noch abschließend gesagt werden, dass es sich bei dem Projekt um ein Proof-of-Concept handelt. Ich habe alle Komponenten nach meinen besten Kenntnissen bezüglich der Architektur und der Sicherheit entworfen. Trotzdem sind Fehler und Schwachstellen natürlich immer möglich.

Gerade bei der Hardware-Sicherheit sei gesagt, dass es keine große Schwierigkeit darstellt, bei einem gesockelten IC den EEPROM und somit die Schlüssel auszulesen. Weiterhin bieten Atmel CPUs meinem Kenntnisstand nach keinen Schutz gegen physikalische Seitenkanalangriffe. Natürlich erfordert diese Angriffsklasse eine gehörige Menge an Know-How und Equipment und ist recht teuer, aber mit einiger Motivation durchaus durchführbar.

Diese Umstände sollen euch nicht davon abhalten, die Plattform zu nutzen, ich möchte damit nur auf mögliche Schwachstellen und Angriffsvektoren hinweisen, die es in jedem Sicherheitsprodukt gibt. Ich möchte euch kein Schlangenöl verkaufen, sondern lieber eine transparente und offene Software bieten.

Ressourcen zum Herunterladen

Quellcode auf Github

Der Quellcode kann via Github bezogen werden:

ArduKey Firmware auf Github

ArduKey-Authentifizierungsserver auf Github

PAM-Modul für ArduKey auf Github


Schlagworte: Arduino, TinyUSBBoard, DIY, Debian Linux

Stolz erzeugt mit Pelican - komplett ohne PHP, Perl, MySQL & Co. Nach oben springen