Ist token_authenticatable von devise sicher?

79

Ich erstelle eine einfache API mit der Rails-API und möchte sicherstellen, dass ich hier auf dem richtigen Weg bin. Ich verwende devise, um Anmeldungen zu verarbeiten, und habe mich für die token_authenticatableOption von Devise entschieden, mit der ein API-Schlüssel generiert wird, den Sie bei jeder Anforderung senden müssen.

Ich kopple die API mit einem Backbone / Marionetten-Frontend und frage mich im Allgemeinen, wie ich mit Sitzungen umgehen soll. Mein erster Gedanke war, den API-Schlüssel nur im lokalen Speicher oder in einem Cookie zu speichern und beim Laden der Seite abzurufen, aber etwas über das Speichern des API-Schlüssels auf diese Weise störte mich aus Sicherheitsgründen. Wäre es nicht einfach, den API-Schlüssel zu erhalten, indem Sie entweder im lokalen Speicher / im Cookie nachsehen oder eine durchgehende Anfrage abhören und ihn verwenden, um sich als Benutzer auf unbestimmte Zeit auszugeben? Ich setze derzeit den API-Schlüssel bei jeder Anmeldung zurück, aber selbst das scheint häufig zu sein - jedes Mal, wenn Sie sich auf einem Gerät anmelden, bedeutet dies, dass Sie bei jedem anderen abgemeldet sind, was eine Art Schmerz ist. Wenn ich diesen Reset fallen lassen könnte, würde er sich unter dem Gesichtspunkt der Benutzerfreundlichkeit verbessern.

Ich kann mich hier völlig irren (und hoffe, dass ich es bin). Kann jemand erklären, ob die Authentifizierung auf diese Weise zuverlässig sicher ist, und wenn nicht, was wäre eine gute Alternative? Insgesamt suche ich nach einer Möglichkeit, wie Benutzer sicher beim API-Zugriff angemeldet bleiben können, ohne häufig eine erneute Authentifizierung zu erzwingen.

Jeff Escalante
quelle

Antworten:

190

token_authenticatableist anfällig für Timing-Angriffe, die in diesem Blog-Beitrag sehr gut erklärt werden . Diese Angriffe waren der Grund, warum token_authenticatableDevise 3.1 entfernt wurde. Weitere Informationen finden Sie im plataformatec-Blogbeitrag .

Um den sichersten Token-Authentifizierungsmechanismus zu erhalten, muss das Token:

  1. Muss über HTTPS gesendet werden.

  2. Muss zufällig sein, von kryptografischer Stärke.

  3. Muss sicher verglichen werden.

  4. Darf nicht direkt in der Datenbank gespeichert werden. Dort kann nur ein Hash des Tokens gespeichert werden. (Denken Sie daran, Token = Passwort. Wir speichern Passwörter nicht im Klartext in der Datenbank, oder?)

  5. Sollte nach einer Logik ablaufen.

Wenn Sie auf einige dieser Punkte zugunsten der Benutzerfreundlichkeit verzichten, erhalten Sie einen Mechanismus, der nicht so sicher ist, wie er sein könnte. So einfach ist das. Sie sollten sicher genug sein, wenn Sie die ersten drei Anforderungen erfüllen und den Zugriff auf Ihre Datenbank jedoch einschränken.

Meine Antwort erweitern und erklären:

  1. Verwenden Sie HTTPS . Dies ist definitiv der wichtigste Punkt, da es sich um Schnüffler handelt.

    Wenn Sie kein HTTPS verwenden, kann viel schief gehen. Zum Beispiel:

    • Um die Anmeldeinformationen des Benutzers (Benutzername / E-Mail / Passwort) sicher zu übertragen, müssten Sie die Digest-Authentifizierung verwenden, aber das reicht heutzutage nicht mehr aus, da gesalzene Hashes brutal erzwungen werden können .

    • In Rails 3 werden Cookies nur von Base64-Codierung umhüllt, sodass sie relativ leicht aufgedeckt werden können. Weitere Informationen finden Sie unter Decodieren von Rails-Sitzungscookies .

      Seit Rails 4 ist der Cookie-Speicher jedoch verschlüsselt, sodass Daten sowohl digital verifiziert als auch für einen Angreifer nicht lesbar sind. Cookies sollten sicher sein, solange sie secret_key_basenicht durchgesickert sind.

  2. Generieren Sie Ihren Token mit:

    Um zu erklären, warum dies notwendig ist, empfehle ich, die sysrandomREADME-Datei und den Blog-Beitrag zum Generieren sicherer Zufallszahlen in verschiedenen Programmiersprachen zu lesen .

  3. Suchen Sie den Benutzerdatensatz anhand der Benutzer-ID, der E-Mail-Adresse oder eines anderen Attributs. Vergleichen Sie dann das Token dieses Benutzers mit dem Token der Anforderung mit Devise.secure_compare(user.auth_token, params[:auth_token]. Wenn Sie auf Rails 4.2.1+ sind, können Sie auch verwenden ActiveSupport::SecurityUtils.secure_compare.

    Sie nicht den Benutzerdatensatz mit einem Rails - Finder wie finden User.find_by(auth_token: params[:auth_token]). Dies ist anfällig für Timing-Angriffe!

  4. Wenn Sie pro Benutzer mehrere Anwendungen / Sitzungen gleichzeitig haben, haben Sie zwei Möglichkeiten:

    • Speichern Sie das unverschlüsselte Token in der Datenbank, damit es von Geräten gemeinsam genutzt werden kann. Dies ist eine schlechte Praxis, aber ich denke, Sie können dies im Namen von UX tun (und wenn Sie Ihren Mitarbeitern DB-Zugriff anvertrauen).

    • Speichern Sie so viele verschlüsselte Token pro Benutzer, wie Sie aktuelle Sitzungen zulassen möchten. Wenn Sie also zwei Sitzungen auf zwei verschiedenen Geräten zulassen möchten, behalten Sie zwei unterschiedliche Token-Hashes in der Datenbank bei. Diese Option ist etwas weniger einfach zu implementieren, aber definitiv sicherer. Es hat auch den Vorteil, dass Sie Ihren Benutzern die Möglichkeit geben können, aktuelle aktive Sitzungen auf bestimmten Geräten zu beenden, indem Sie ihre Token widerrufen (genau wie bei GitHub und Facebook).

  5. Es sollte einen Mechanismus geben, der das Ablaufen des Tokens bewirkt. Berücksichtigen Sie bei der Implementierung dieses Mechanismus den Kompromiss zwischen UX und Sicherheit.

    Google verfällt ein Token, wenn es sechs Monate lang nicht verwendet wurde .

    Facebook verfällt ein Token, wenn es zwei Monate lang nicht verwendet wurde :

    Native mobile Apps, die die SDKs von Facebook verwenden, erhalten langlebige Zugriffstoken, die etwa 60 Tage lang gültig sind. Diese Token werden einmal täglich aktualisiert, wenn die Person, die Ihre App verwendet, eine Anfrage an die Server von Facebook stellt. Wenn keine Anforderungen gestellt werden, läuft das Token nach etwa 60 Tagen ab und die Person muss den Anmeldefluss erneut durchlaufen, um ein neues Token zu erhalten.

  6. Aktualisieren Sie auf Rails 4, um den verschlüsselten Cookie-Store zu verwenden. Wenn Sie dies nicht können, verschlüsseln Sie den Cookie-Speicher selbst, wie hier vorgeschlagen . Es wäre absolut kein Problem, ein Authentifizierungstoken in einem verschlüsselten Cookie-Speicher zu speichern.

Sie sollten auch einen Notfallplan haben, z. B. eine Rechenaufgabe, um eine Teilmenge von Token oder jedes einzelne Token in der Datenbank zurückzusetzen.

Um Ihnen den Einstieg zu erleichtern , können Sie in diesem Artikel (von einem der Autoren von Devise) nachlesen , wie die Tokenauthentifizierung mit Devise implementiert wird. Schließlich sollte der Railscast zum Sichern einer API hilfreich sein.

Ashitaka
quelle
Super, das hilft sehr - danke! Dies wird mit ziemlicher Sicherheit die richtige Antwort erhalten. Bounty liegt bei Ihnen, wenn Sie Ihre Meinung / Empfehlung (speziell) zum besten Umgang mit der API-Authentifizierung hinzufügen
Jeff Escalante
1
Während beide Methoden eine zufällige Zeichenfolge urlsafe_base64generieren , wird eine url-sichere Zeichenfolge generiert. Es ist alles im Namen. Verwenden Sie, es sei denn, Sie möchten Ihr Token in Ihrer URL verwenden ( was Sie nicht sollten ) hex.
Ashitaka
2
Token! = Passwort. Es ist nichts Falsches daran, ein Token im Klartext zu speichern. Das Problem beim Speichern von Passwörtern im Klartext ist, dass das Passwort woanders verwendet werden kann, was bei Ihrem Token nicht der Fall sein sollte.
Fatfrog
2
@fatfrog Nr. Token == Passwort. Wenn ein Hacker oder ein verärgerter Mitarbeiter Zugriff auf Ihre Datenbank hat, sollte er sich nicht als bestimmter Benutzer oder Administrator authentifizieren können.
Ashitaka
1
Ich bin anderer Meinung, wenn ein Hacker oder verärgerter Mitarbeiter Zugriff auf Ihre Datenbank hat, sind Token das Letzte, worüber Sie sich Sorgen machen müssen. Sie haben bereits Ihre Daten.
Fatfrog
3

Sie können versuchen, rails4 mit Ihrer API zu verwenden. Sie bietet mehr Sicherheit und verwendet devise 3.1.0rc

Für Token, Session Store, gehen Sie zu http://ruby.railstutorial.org/chapters/sign-in-sign-out und http://blog.bigbinary.com/2013/03/19/cookies-on-rails .html für mehr Verständnis.

Zuletzt sollten Sie diese Art der Verschlüsselung und Entschlüsselung " Gespeicherte verschlüsselte Daten können nicht entschlüsselt werden " durchlaufen , um mehr Sicherheit zu erhalten.

Gaurav Sharma
quelle
Hat jemand ein Beispiel für eine maßgeschneiderte Alternative?
Daniel Morris