Sicheres Speichern von Passwörtern in SQL Server Datenbanken

Wir sind uns vermutlich alle einig, dass die Auswahl eines Passwortes mit Bedacht und höchster Sorgfalt vorgenommen werden sollte. Wir sichern mit Passwörtern wichtige Daten und Informationen, die nur für den eigenen Gebrauch gedacht sind und bestenfalls nicht an Dritte weitergegeben werden sollten. Eine Mischung aus Buchstaben, Sonderzeichen und Zahlen ist dabei essenziell. Einfache Wörter oder Wortkombinationen, die sich leicht ableiten lassen, sind nicht sinnvoll und fahrlässig mit dem Umgang Ihrer personenbezogenen Daten.

Jedoch reichen manchmal noch so gut ausgetüftelte Passwörter nicht aus, wenn die entsprechenden Kennwörter unsicher auf den Datenbanken gespeichert werden. Wir zeigen Ihnen mit diesem Artikel, wie Sie Kennwörter in einer Datenbank verschlüsselt speichern können.

In Datenbankanwendungen können die Kennwörter auch in der Datenbank gespeichert werden. Wenn Sie auch Ihre Kennwörter in der Datenbank speichern möchten, ist es wichtig, dass die Kennwörter sorgfältig verschlüsselt werden und nicht offensichtlich in einer der Tabellen gespeichert werden. So schützen wir uns vor Hackerangriffen und verhindern größere Schäden.

Lösungsansatz

Ein hilfreiches Mittel zu sicheren Kennwortverschlüsselung ist die Verwendung von Einweg-Hashing-Algorithmen. Diese Algorithmen ordnen den Eingabewert einer verschlüsselten Ausgabe zu und generieren für dieselbe Eingabe, denselben Ausgabetext. Wie aber die Bezeichnung schon vermuten lässt, lässt sich die Verschlüsselung nur one-way vornehmen. Im Umkehrschluss bedeutet das für uns, dass wir mit einer verschlüsselten Ausgabe nicht zum ursprünglichen Eingabewert zurückkehren können.

Wir verwenden dafür die HASHBYTES Funktion in SQL Server, die einen Hash für einen bestimmten, vom Algorithmus generierten, Eingabewert zurück gibt. Es gibt eine Vielzahl an Algorithmen für diese Funktion, die wir verwenden können. Diese sind MD2, MD4, MD5, SHA, SHA1 und ab SQL Server 2012 auch SHA2_256 und SHA2_512. Für unser Beispiel verwenden wir den stärksten Algorithmus – SHA2_512. Dieser generiert einen 130-Symbol-Hash und verwendet dabei 64 Bytes. Je stärker der Algorithmus ist, desto mehr Zeit wird er für das Hashing benötigen.

In unserem Beispiel erstellen wir eine Tabelle mit Benutzerdaten:

CREATE TABLE dbo.[User]
(
    UserID INT IDENTITY(1,1) NOT NULL,
    LoginName NVARCHAR(40) NOT NULL,
    PasswordHash BINARY(64) NOT NULL,
    FirstName NVARCHAR(40) NULL,
    LastName NVARCHAR(40) NULL,
    CONSTRAINT [PK_User_UserID] PRIMARY KEY CLUSTERED (UserID ASC)
)

Zusätzlich erstellen wir eine einfache Prozedur, um die Benutzerdaten einfügen zu können.

CREATE PROCEDURE dbo.uspAddUser
    @pLogin NVARCHAR(50), 
    @pPassword NVARCHAR(50), 
    @pFirstName NVARCHAR(40) = NULL, 
    @pLastName NVARCHAR(40) = NULL,
    @responseMessage NVARCHAR(250) OUTPUT
AS
BEGIN
    SET NOCOUNT ON

    BEGIN TRY

        INSERT INTO dbo.[User] (LoginName, PasswordHash, FirstName, LastName)
        VALUES(@pLogin, HASHBYTES('SHA2_512', @pPassword), @pFirstName, @pLastName)

        SET @responseMessage='Success'

    END TRY
    BEGIN CATCH
        SET @responseMessage=ERROR_MESSAGE() 
    END CATCH

END

Wir können sehen, dass die Prozedur ein Kennwort als Eingabeparameter in verschlüsselter Form verwendet und in die Datenbank HASHBYTES (SHA2_512’ @pPassword) einfügt.

Die Prozedur können wir anschließend wie folgt ausführen:

DECLARE @responseMessage NVARCHAR(250)

EXEC dbo.uspAddUser
          @pLogin = N'Admin',
          @pPassword = N'123',
          @pFirstName = N'Admin',
          @pLastName = N'Administrator',
          @[email protected] OUTPUT

SELECT *
FROM [dbo].[User]

Wir können nun sehen, dass der Text des Passworts nicht lesbar ist und mit einem Hash verschlüsselt wurde. Was uns aber trotzdem nicht vollends vor Hackerangriffen schützt. Angreifer können beispielsweise Hashes für einfache und allgemeine Kennwörter generieren und diese Zuordnung in der Tabelle speichern. Mit dieser Tabelle können Angreifer die Hashes der Zuordnungstabelle mit den Kennwort-Hashes der Benutzer vergleichen und somit auf Benutzerdaten zugreifen. Auch hier nochmal der Tipp: Verwenden Sie keine einfachen Passwörter und nutzen Sie bestenfalls den stärksten verfügbaren Verschlüsselungsalgorithmus zur Sicherung Ihrer Daten.

Optional besteht auch die Möglichkeit, stärkere Hashs zu erstellen, selbst wenn der Benutzer ein vergleichsweise schwaches Passwort verwendet. Der besagte Hash besteht aus einer Kombination des Passworts und einem zufällig generierten Text. Diesen zufällig generierten Text nennt man in der Kryptographie „Salt“. Dieses Salt erschwert dem Angreifer das Hacken. Haben jedoch mehrere Benutzer dasselbe Kennwort, ist auch das entsprechende Kennwort-Hash identisch. Ist zusätzlich auch noch das „Salt“ identisch, können Angreifer nicht nur auf Ihr Passwort, sondern auch auf das der Kollegen zugreifen. Sie sollten entsprechend darauf achten, verschieden generierte Salts zu verwenden um solche Situationen zu vermeiden.

Im folgenden Beispiel ändern wir die Abfrage entsprechend, sodass bei der Kennwortverschlüsselung ein Salt verwendet wird. Folgenden Befehl verwenden wir um ein Salt zu generieren: UNIQUEIDENTIFIER 

ALTER TABLE dbo.[User] ADD Salt UNIQUEIDENTIFIER 
GO

ALTER PROCEDURE dbo.uspAddUser
    @pLogin NVARCHAR(50), 
    @pPassword NVARCHAR(50),
    @pFirstName NVARCHAR(40) = NULL, 
    @pLastName NVARCHAR(40) = NULL,
    @responseMessage NVARCHAR(250) OUTPUT
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @salt UNIQUEIDENTIFIER=NEWID()
    BEGIN TRY

        INSERT INTO dbo.[User] (LoginName, PasswordHash, Salt, FirstName, LastName)
        VALUES(@pLogin, HASHBYTES('SHA2_512', @pPassword+CAST(@salt AS NVARCHAR(36))), @salt, @pFirstName, @pLastName)

       SET @responseMessage='Success'

    END TRY
    BEGIN CATCH
        SET @responseMessage=ERROR_MESSAGE() 
    END CATCH

END

Wir verkürzen nun die Tabelle und führen die Abfrage erneut aus:

TRUNCATE TABLE [dbo].[User]

DECLARE @responseMessage NVARCHAR(250)

EXEC dbo.uspAddUser
          @pLogin = N'Admin',
          @pPassword = N'123',
          @pFirstName = N'Admin',
          @pLastName = N'Administrator',
          @[email protected] OUTPUT

SELECT UserID, LoginName, PasswordHash, Salt, FirstName, LastName
FROM [dbo].[User]

Wir erhalten folgendes Ergebnis:

Wir sehen nun, dass das Salt in der Tabelle als Klartext ausgewiesen ist. Es ist daher auch nicht nötig, es nochmal zu verschlüsseln. Erstellen wir jetzt eine weitere Abfrage, um den Benutzer mithilfe des verschlüsselten Kennworts mit dem Salt zu authentifizieren:

CREATE PROCEDURE dbo.uspLogin
    @pLoginName NVARCHAR(254),
    @pPassword NVARCHAR(50),
    @responseMessage NVARCHAR(250)='' OUTPUT
AS
BEGIN

    SET NOCOUNT ON

    DECLARE @userID INT

    IF EXISTS (SELECT TOP 1 UserID FROM [dbo].[User] WHERE [email protected])
    BEGIN
        SET @userID=(SELECT UserID FROM [dbo].[User] WHERE [email protected] AND PasswordHash=HASHBYTES('SHA2_512', @pPassword+CAST(Salt AS NVARCHAR(36))))

       IF(@userID IS NULL)
           SET @responseMessage='Incorrect password'
       ELSE 
           SET @responseMessage='User successfully logged in'
    END
    ELSE
       SET @responseMessage='Invalid login'

END

..und erhalten folgendes Ergebnis:

Fazit

Durch das verschlüsselte Speichern von Kennwörter in Datenbanken und die zusätzliche Verwendung von zufällig generierten Texten (Salt) minimieren wir das Risiko eines Hacker-Angriffs. Mit dem Befehl UNIQUEIDENTIFIER erstellen wir ein starkes und eindeutiges Salt, welches zur Authentifizierung von Benutzern verwendet werden kann.


→ Hier findest Du den Artikel zum direkten PDF-Download: madafa.de/download/artikel-downloads/