Warum überhaupt Benutzerkennwörter speichern?


10

Ich sehe gelegentlich Fragen, wie Benutzerkennwörter für eine Webanwendung sicher gespeichert werden können (mit einem RDBMS spreche ich nicht von Facebook oder Twitter). Die übliche Antwort lautet "Salt das Passwort, dann Hash es mit einem starken Algorithmus wie TDES oder SHA512".

Meine Frage lautet: Warum sollte ich mich als RDBMS-Benutzer überhaupt mit der problematischen Speicherung von Passwörtern beschäftigen, da die meisten Engines über einen integrierten Authentifizierungsmechanismus verfügen?

Wenn beispielsweise ein Benutzer X in meiner Webanwendung ein Kontonutzerkennwort Y erstellen möchte, wie wird die folgende Abfrage falsch ausgegeben:

CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;

Dann kann der Benutzer in meiner Anwendung mit seinen Anmeldeinformationen eine Verbindung zur Datenbank herstellen, und ich muss mich überhaupt nicht um die Kennwortverwaltung kümmern.

Ich sehe mehrere Vorteile dieser Methode:

  • Wenn das RDBMS entscheidet, dass der Verschlüsselungsalgorithmus geändert werden muss, muss ich nichts anfassen, nur um die Sicherheitsupdates anzuwenden.
  • Es ist für mich einfach, die Benutzerberechtigungen zu verwalten. Wenn ein Benutzer in die Rolle eines Administrators befördert wird, muss ich den Benutzer nur der entsprechenden Gruppe hinzufügen.
  • SQL-Injektionen sind jetzt bedeutungslos, da ich Berechtigungen verwalte, um jedem Benutzer in der Datenbank genau das zu ermöglichen, was ich zulassen möchte (z. B. in einem Forum wie SO, Hinzufügen neuer Beiträge, Beantworten von Beiträgen, Kommentieren und Bearbeiten / Löschen seiner eigenen Fragen / Antworten / Kommentare);
  • Ein Benutzerkonto "anonym" kann für nicht authentifizierte Verbindungen zu meiner Anwendung verwendet werden.
  • Jeder Benutzer ist der Eigentümer der von ihm bereitgestellten Daten.

Aber bei praktisch jeder Frage, die ich zu diesem Thema sehe, scheint es einen allgemeinen Konsens zu geben, dass dies nicht die Art und Weise ist, wie Dinge getan werden müssen. Meine Frage ist: warum?

Hinweis: Der dritte Punkt wird von Richtlinien in PostgreSQL und Sicherheitsrichtlinien in Microsoft SQL Server zugelassen. Mir ist klar, dass diese Konzepte Neulinge sind, aber warum wird die von mir beschriebene Technik nicht zur Standardmethode für den Umgang mit Benutzerkonten?


2
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Paul White 9

Die übliche Antwort ist übrigens falsch. Sie sollten das Passwort salzen und es dann mit einem langsamen Algorithmus wie bcrypt oder argon2 hashen.
Tgr

Antworten:


27

Für viele Anwendungen möchten sie nicht, dass einzelne Benutzerkonten eine Verbindung zur Datenbank herstellen. Die Benutzer / Kennwörter / Rechte / Berechtigungen werden alle auf der Anwendungsebene verarbeitet, und ein einziges dediziertes Dienstkonto wird verwendet, um eine Verbindung zum Datenbank-Backend herzustellen.

Als DBA möchte ich nicht auf Datenbankebene die 10.000 aktiven Benutzer einer mittelgroßen öffentlich zugänglichen Webanwendung oder die 2+ Millionen Benutzer einer plötzlich beliebten App verwalten müssen.

In einem sehr realen Sinne ist dies ein Unterschied in der Philosophie zwischen Anwendungsentwicklern und Datenbankentwicklern / Datenbankadministratoren.

Viele / die meisten Anwendungsentwickler werden die Verantwortung für wichtige Aspekte der App-Funktionalität und / oder Geschäftsregeln nicht auf die Datenbankebene übertragen wollen. Stattdessen betrachten sie die Datenbank als Werkzeug zum einfachen Speichern und Abrufen von Daten.

In einigen Fällen kann dies kurzsichtig sein; Viele RDBMS verfügen über fantastische Funktionen, die das Leben von App-Entwicklern erheblich vereinfachen können (Sicherheit auf Zeilenebene, Spaltenindizes, Dateistream-Speicher usw.).

Einige dieser cooleren Funktionen sind jedoch nur in neueren Versionen verfügbar, und Unternehmen können vorhandene Umgebungen nicht immer schnell aktualisieren (siehe diese Tabelle aus dem Jahr 2014 ).

In anderen Fällen wird die Behandlung dieser Dinge auf der Anwendungsebene bevorzugt (und nicht nur aus Gründen der Portabilität der Datenbankplattform denke ich offen, dass die Behauptung übertrieben ist).


2
Es gibt einen "heiligen Krieg", ob Geschäftslogik in die Anwendung oder in die Datenbank geht. Wenn Sie eine Anwendung erstellt haben, in der sich die gesamte Geschäftslogik (insbesondere die Sicherheit) in der Datenbank befindet (unter Verwendung gespeicherter Prozeduren, Ansichten usw.), gibt es möglicherweise ein Argument für die Verwendung von Datenbanksicherheitsmechanismen, da niemand eine direkte Verbindung herstellen und sich um Ihre herum bewegen kann Sicherheit. Ich stimme voll und ganz zu, dass Sie vermeiden sollten, einen Sicherheitsmechanismus (dh Login / Pasword) in einer benutzerdefinierten Tabelle neu zu erstellen. Warum tun Sie das, wenn Sie bereits über Active Directory / O365-Sicherheit verfügen?
Nick.McDermaid

1
@ Nick.McDermaid Ich möchte sicherstellen, dass ich die Geschäftslogik zwischen DB und Anwendung fair mische, um das Potenzial zukünftiger Entwickler auszuschließen, eine verdammte Ahnung davon zu haben, was vor sich geht. Außerdem hilft es mir, meine Arbeitsplatzsicherheit aufrechtzuerhalten, da niemand verrückt ist genug, um es verwalten zu wollen.
Der Kommissar

Werfen Sie einen Webdienst und einen Tomcat-Anwendungsserver hinein und Sie könnten für IBM
Nick.McDermaid

8

Die Trennlinie wird zu diesem Zeitpunkt etwas flauschig, aber ich würde Benutzer und Berechtigungen auf Datenbankebene als Teil des Schemas betrachten, nicht als Teil der Daten, und im Allgemeinen haben Anwendungen keinen Platz, um das Schema zu ändern (es gibt, wie immer Ausnahmen von dieser Regel).

Ich möchte den Anwendungen lieber nicht die Berechtigungen erteilen, die sie zum Verwalten von Schemaobjekten (Anmeldungen, Benutzer und Berechtigungen) benötigen, da neue Benutzer benötigt werden und alte verlassen werden. Wenn diese Anwendung gehackt wird, hat der Angreifer Zugriff auf diese Berechtigungen Dies erleichtert das weitere Öffnen der Datenbank. In MS SQL Server sind Anmeldungen, sofern Sie keine vollständig enthaltenen Datenbanken verwenden, Objekte auf Serverebene. Daher müssen Sie Rechte über die einzelne Anwendungsdatenbank hinaus vergeben, was das Risiko noch erhöht.

Selbst wenn Sie auf Datenbankebene Konten pro Anwendungsbenutzer haben, benötigen Sie Benutzerkonten auf Anwendungsebene, um nicht authentifizierte Anforderungen zu verarbeiten. Dies bedeutet, dass die Anwendung Informationen aus der Datenbank benötigt, bevor sich der Anwendungsbenutzer erfolgreich authentifiziert hat (möglicherweise auch) Statusinformationen auf dem Begrüßungs- / Anmeldebildschirm anzeigen?).

Auch wenn die Portabilität zwischen Datenbank-Engines ein Ziel ist (vielleicht möchte Ihre App sowohl auf MySQL als auch auf Postgres ausgeführt werden können?), Müssen Ihre Anwendungen die Benutzer- / Anmeldeverwaltungsfunktionen für jede Engine abstrahieren, da sie nicht Standard zwischen ihnen sind - Wenn Sie sich darum bemühen, können Sie Kennwörter auch selbst implementieren und die gewünschten Verwaltungsoptionen erhalten, anstatt den niedrigsten gemeinsamen Funktionsumfang der Engines zu akzeptieren.


1
Ok, die "Anwendung sollte das Schema nicht ändern" ist meiner Meinung nach der erste gute Punkt gegen die von mir vorgeschlagene Technik. Das anonyme Konto, das neue Benutzer erstellen kann, muss jedoch nur neue Benutzer mit dem grundlegendsten Zugriff erstellen können. Nur Administratoren können Benutzer befördern und Benutzer löschen, was in Anwendungen wohl erwünscht ist :-) Die allgemeinen Daten sind für den anonymen Benutzer sichtbar, sodass diese Verbindung für Inhalte verwendet werden kann, für die keine Authentifizierung erforderlich ist. Portabilität ist auch ein guter Punkt, aber ich denke, Benutzerbefehle sind jetzt Teil des Standards (nicht sicher, es war nicht vor Jahren)
Fabian Pijcke

Übrigens: Wenn ein Hacker mit dieser Einstellung als anonymer Benutzer Zugriff auf die Datenbank erhält, kann er so viele Benutzer erstellen, wie er möchte. Dies ist jedoch kein Sicherheitsproblem. Er kann die Datenbank auch mit einem der folgenden Elemente aufblähen die erstellten Konten, das wäre ärgerlich, aber wieder kein Sicherheitsproblem (und er könnte es sowieso auch über die Standardschnittstelle tun, es wäre allerdings viel langsamer: p)
Fabian Pijcke

3
Ich bin damit einverstanden, dass Benutzer aus Sicherheitsgründen auf Datenbankebene besser wären. Dies ist jedoch grundsätzlich nicht möglich, z. B. mit Online-Shops, in denen möglicherweise 50 Millionen Benutzer registriert sind. Jeder müsste ein Datenbankbenutzer sein. Plus: Dies funktioniert normalerweise nicht gut mit Webanwendungen, die einen Verbindungspool verwenden.
a_horse_with_no_name

6

Wiederholung der Frage

Warum überhaupt Benutzerkennwörter speichern?

Die einfachste Antwort ist, dass Sie dies tun müssen. Sie speichern weiterhin Passwörter in Ihrer alternativen Methode. Sie verwenden lediglich das integrierte System der Datenbank, um den Speicher zu verwalten. Ihre Methode ist also nur so gut wie die Ihrer Datenbank. Das ist vielleicht immer noch besser als alles, was Sie sonst tun, aber es vermeidet nicht die Speicherung. Es geht wirklich nur darum, Codierungsspeicher zu vermeiden.

Es könnte auch nicht besser sein. Wenn ich eine Datenbank kompromittiere und Kopien der Dateien erhalte, kann ich direkt auf die Tabellen zugreifen. Es macht also wenig Sinn, ein brillantes Passwortverwaltungssystem zu verwenden. Denn wenn jemand auf die Tabelle auf Systemebene zugreifen kann, die die Kennwörter oder Hash-Kennwörter enthält, kann er auch direkt auf die Dateien zugreifen. Warum sich mit dem Knacken von Passwörtern beschäftigen, wenn Sie die Daten bereits haben? Es ist auch nicht so, dass Sie die Daten einfach verschlüsseln können. Jeder Benutzer muss darauf zugreifen können. Die Verschlüsselung auf Benutzerebene funktioniert also nicht so gut.

Aber was Sie wirklich zu fragen scheinen, ist

Warum ein Authentifizierungsschema auf Anwendungsebene verwenden, wenn die Datenbank bereits über eines verfügt?

Sicherheit

Andere haben die Möglichkeit ignoriert, eine sicherere Version zu schreiben, und eine Reihe von Gründen vorgeschlagen. Ich stimme im Allgemeinen zu. Aber es gibt noch eine andere, die noch niemand erwähnt hat. Sie gefährden die Sicherheit Ihrer Datenbank.

In diesem System verfügt jeder Benutzer Ihrer Anwendung über einen Datenbankbenutzer und ein Kennwort. Sicher, es ist ein begrenzter Benutzer, aber es ist immer noch ein Benutzer, der eine Verbindung zur Datenbank herstellen kann. Selbst wenn Sie die Sicherheit auf Zeilenebene verwenden, ermöglichen Sie Endbenutzern weiterhin, Informationen zur Datenbankverbindung zu erhalten. Wenn es jemals einen Exploit gibt, bei dem ein Benutzer sogar Zugriff auf Tabellenebene erhalten kann, haben Sie Ihre Datenbank für Angriffe geöffnet. Einige Exploits gingen darüber hinaus auf den Administratorzugriff über.

In den Schichten der Sicherheitszwiebel ist das normale System:

  • Datenbank, die nur Verbindungen von bestimmten Computern zulässt.
  • Datenbank erlaubt Verbindungen nur als bestimmte Benutzer / Passwort-Kombinationen.
  • Server mit Datenbankberechtigungen, die Verbindungen von Anwendungen zulassen.
  • Anwendungen werden auf dem Server ausgeführt.
  • Anwendungen verfügen über Datenbankverbindungsinformationen mit eingeschränkten Berechtigungen.
  • Anwendungen authentifizieren Benutzer, bevor sie die Datenbank ändern können (außer möglicherweise, um neue Konten zu erstellen).

In diesem System:

  • Endbenutzer kennen Benutzer- / Kennwortkombinationen, die in der Datenbank funktionieren, allerdings mit sehr geringen Berechtigungen.
  • Sie müssen nur einen Server umfassen oder sich überzeugend als autorisierter Server ausgeben.

Wir haben die gesamte Sicherheitsstufe der Anwendung verloren. Und wir haben freiwillig einen Teil der Datenbankebene aufgegeben. Wir brauchen also nur zwei Exploits:

  1. Parodieren oder gefährden Sie einen autorisierten Server.
  2. Erhöhen Sie den Zugriff des Kontos mit eingeschränkten Berechtigungen.

Wenn wir diese beiden Dinge tun können, haben wir Zugriff auf die Datenbank. Also gehen wir von drei Schichten auf zwei. (Die dritte Schicht im normalen System besteht darin, dass Sie einen gültigen Benutzer benötigen, um eine Verbindung zur Datenbank herzustellen.)

Sie werden viel mit der Verwaltung dieser Konten zu tun haben. Was ist, wenn Sie einen Fehler machen? Anstatt Benutzer X auf bestimmte Zeilen zu beschränken, gewähren Sie allen Zugriff auf eine kritische Tabelle. Solche Dinge werden normalerweise manuell erledigt und es gibt nur wenige davon, so dass sie leicht zu prüfen sind. In Ihrem System können Sie jedoch Tausende oder Millionen oder sogar Milliarden von Benutzerkonten erstellen, von denen jedes seinen eigenen eigenwilligen Zugriff hat.

Skaliert das System der Datenbank auf Millionen oder Milliarden Benutzer? Wenn ja, wie steht es mit der Anzahl der Regeln? Wenn jeder Benutzer hundert oder mehr Regeln darüber aufstellt, auf was er zugreifen kann und was nicht, skaliert das auf eine Milliarde Benutzer? Sie nehmen ein normalerweise kleines System und machen es groß. Das wird nicht unbedingt funktionieren. Während Sie wachsen, können Systembeschränkungen auftreten.


5

Was Sie beschreiben, behandelt die Authentifizierung, jedoch nicht die Autorisierung (auf welche Daten der Benutzer zugreifen kann) oder nur im einfachsten Anwendungsfall.

So fahren Sie mit Ihrem Beispiel mit stackexechange fort: Wie würden Sie gelöschte Beiträge nur für Benutzer mit hohen Wiederholungszahlen sichtbar machen? Für Zugriffsregeln benötigen Sie also weiterhin Logik im Code. Anstatt die Zugriffslogik zwischen Datenbankregeln und anwendbaren Zugriffsregeln zu teilen, ziehen es die meisten Entwickler vor, sie alle am selben Ort zu haben.

Sie benötigen auch eine Tabelle zum Speichern der Benutzerinformationen: Ein Benutzer ist nicht nur ein Benutzername + Passwort. Er hat eine E-Mail, einen Ruf und so weiter. Sie benötigen also weiterhin die Benutzertabelle, die Sie sicherstellen müssen, dass sie mit der Datenbankbenutzertabelle synchron ist, sofern Sie darauf zugreifen können.

Mit Ihrer Lösung können Sie einfach eine Kennwortspalte weglassen, die nicht so schwer auszufüllen ist: Es gibt gute Bibliotheken und Dokumentationen zum Umgang mit / Hash-Kennwörtern.

Ein anderer Punkt: Wie würden Sie einen Verbindungspool erstellen? Ich kenne nur jdbc (java <-> db) und Sie müssen einen Benutzernamen + ein Passwort angeben, um eine Verbindung herzustellen, die Sie dann bündeln können.

Ich dachte an einige andere Punkte, deren Umsetzung schwieriger / komplizierter sein wird als auf die etablierte Weise:

  • Umgang mit der Passwortwiederherstellung
  • 2 Jahre nach der ersten Implementierung bittet Sie Ihr Produktmanager, Unterstützung für das Oauth-Schema hinzuzufügen oder die Doppelfaktorauthentifizierung zuzulassen

So etwas wie CREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)beantwortet Ihre erste Frage. Ich habe nie gesagt, dass ich keine Benutzertabelle mehr benötige, und die Synchronisierung mit der DB-Benutzertabelle ist etwas schwierig, aber möglich. Der Hauptpunkt der diskutierten Technik ist die Sicherheit. Was den Verbindungspool betrifft, arbeite ich mit OCaml und ich muss sagen, dass ich nicht verstehe, warum ich einen Verbindungspool benötigen würde. Ich verwende derzeit eine Hash-Map, die Cookie-Werte mit 0-ary-Funktionen verknüpft, die Verbindungen zurückgeben :-)
Fabian Pijcke

5
Der Verbindungspool wird implementiert, um die Leistung zu verbessern: Mit ihnen müssen Sie nicht für jede Benutzeranforderung eine Verbindung herstellen (Sie sparen also CPU / Io / Latenz beim Erstellen der TCP-Verbindung + den gesamten Verbindungs- und Authentifizierungsaustausch mit der Datenbank). Was die Richtliniendefinition betrifft: Ihre Datenbank überprüft ständig den Zugriff auf jeden Zugriff auf Daten, auch wenn Sie diese bereits einmal überprüft haben. Auch "Zugriff verweigert oder verboten" ist nicht dasselbe wie "OK, kein Ergebnis". Ich bin mir nicht sicher, ob die Sicherheitsleute die OK-Version bevorzugen würden.
Thierry

3
Fabian, Verbindungspooling ist in jeder Größenordnung von grundlegender Bedeutung. Es ist wirklich eine Standardeinstellung, die Sie nicht einmal in Betracht ziehen würden, nicht zu verwenden. Hier sind einige Benchmarks, um Ihnen eine Vorstellung davon zu geben, wie wichtig es ist: 600-fache Leistungssteigerung mit Verbindungspooling ( vladmihalcea.com/2014/04/17/the-anatomy-of-connection-pooling ) und über 4.000-fache Leistungssteigerung mit Verbindungspooling ( progress.com/tutorials/jdbc/… ). Es ist ein Unterschied von mehreren Größenordnungen, es ist kein "schön zu haben", Apps würden ohne es zum Stillstand kommen.
Ivan McA

1
Interessante Zahlen. Und in der Tat habe ich noch nie eine Anwendung gesehen, die keine Verbindungspools verwendet. Aber ich wusste nicht (und erwartete), dass sie so viel beschleunigen würden. Der andere Aspekt, den Sie mit dem Verbindungspool erhalten, ist die Ressourcensteuerung: Dank dieser Tatsache wird Ihre Anwendung durch eine enorme Zunahme von Clients, die versuchen, eine Verbindung auf einmal herzustellen, langsam, aber Ihre Datenbank wird nicht so stark beeinträchtigt (wenn der Pool gut konfiguriert ist). .
Thierry

Ok, ich habe gerade nach weiteren Informationen zu Verbindungspools gesucht und bin damit einverstanden, dass dies ein sehr gültiger Punkt ist, sobald die Website mehr als einhundert Verbindungen pro Sekunde verarbeiten muss, was nicht so hoch ist. Es scheint, dass jede Verbindung in PostgreSQL ungefähr 10 MB RAM verbraucht! Ich hätte nie gedacht, dass es so viel ist.
Fabian Pijcke

1

Ein weiterer Punkt: Mit vielen [1] Webanwendungen können Sie sich online über die App selbst registrieren und ein Benutzerkonto erstellen. Was bedeutet, dass Ihr anonymer Benutzer (der die geringsten Berechtigungen haben sollte, die man annehmen würde) Rechte haben muss, um Benutzer zu erstellen und Berechtigungen zu erteilen!

OK, es ist möglicherweise möglich, die Berechtigungen einzuschränken und übergeordneten Benutzern mehr Berechtigungsoptionen zu gewähren (ich bin mir jedoch nicht bewusst, dass dies nicht der Fall ist - ist "Gewähren von Berechtigungen" nicht oft ein einzelnes Privileg). Trotzdem bedeutet es, etwas mit Berechtigungen online zu stellen, auf das sich jeder hacken kann. Ich bin mir ziemlich sicher, dass mein DBA mich nicht mögen würde, wenn ich das tun würde :)

Ich weiß, dass dieses Problem auf einer Ebene ohnehin besteht, aber Sie haben Schutzschichten, insbesondere beim Löschen von Daten, wenn Sie der Web-App nicht erlauben, DB-Benutzer zu verwalten.

Dies würde auch die Verwendung gepoolter oder wiederverwendeter DB-Verbindungen verhindern.

[1] Die meisten würde ich sagen, aber keine Zahlen, um dies zu belegen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.