Tutorial - Passwort besser absichern mit einem Salt

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Tutorial - Passwort besser absichern mit einem Salt

      Willkommen zu einem kleinen Tutorial von mir!

      Ich werde euch in diesem Tutorial das Hashen / Salten von Passwörtern in Datenbanken per Pawn näherbringen.
      Das Salten von Passwörtern sorgt heutzutage für mehr Sicherheit bei Datenbankzugriff von fremden Personen.

      Beim Salten von Passwörtern wird ein zufällig erstellter Datensatz zum Verschlüsseln der Passwörter verwendet.
      Somit wird ein nahezu einzigartiger Hash erstellt, der von Crack Datenbanken nicht aufzufinden werden ist. (Beispiel Cracker)

      Nun, man könnte seine Passwörter genau so in SHA Encoden oder andere Encodings verwenden, meiner Meinung nach bringt das Salten aber die meiste Sicherheit.
      Auch für SHA gibt es Datenbanken, die für das Cracken von Strings da sind, um eventuelle Passwörter zu finden.


      Was benötigt ihr?
      1. Etwas Ahnung von Pawn und MySQL
      2. Natürlich wie oben schon genannt, MySQL oder andere Datenbanken (Dieses Tutorial basiert auf MySQL)
      3. Ein bisschen Verständnis was ihr eigentlich tut



      Nun fangen wir doch eigentlich mit dem an was wir benötigen, im sinne von MySQL.
      Ihr solltet eine Tabelle mit mindestens 2 Spalten haben für "Password" und "Salt".

      Wir überlegen nun, wie können wir denn eigentlich das Passwort mit dem Salt in Verbindung bringen.
      Als erstes sollten wir den Salt generieren und allgemein einen Account erstellen lassen.

      Das ist der Schritt in dem wir den Salt in der Datenbank speichern und das Passwort sozusagen mit dem Salt verschlüsseln.
      Dadurch das wir das eigentliche Passwort garnicht in der Datenbank abspeichern, ist es sozusagen unmöglich das Resultat auszulesen.

      Also was benötigen wir für unser Salt? Für mich persönlich reicht es aus einen zufälligen Integer zu verwenden.
      Und kommt dabei das Stichwort "random" in den Kopf, eine Pawnfunktion die uns eine zufällige Ganzzahl zurück gibt.

      Wir lassen uns also mit einem Dialog ein Fenster anzeigen in dem wir unser "Passwort" angeben und verarbeiten.

      PAWN-Quellcode

      1. if(dialogid == DIALOG_REGISTER){ if(response) { if(strlen(inputtext) > 6) { new Query[256], Salt[64], Password[128]; format(Salt, "%i", random(999999)); //Generieren vom Salt format(Salt, "%s", MD5_Hash(Salt)); //Umwandeln des Salt's in MD5 format(Password, "%s", MD5_Hash(inputtext)); //Passwort in MD5 Hashen format(Password, "%s%s", Salt, Password); //Gehashter Salt und Passwort zusammenfügen format(Password, "%s", MD5_Hash(Password)); //Ingesammt nochmal Hashen mysql_format(Handle, Query, 256, "INSERT INTO users (username, password, salt) VALUES ('%e', '%e', '%e')", Playername(playerid), Password, Salt); mysql_query(Handle, Query, "", ""); //Den Query von oben ausführen } else { SendClientMessage(playerid, -1, "Passwort muss mindestens 6. Zeichen lang sein!"); } } else { Kick(playerid); }}


      Wie im Script mit Kommentaren (//) beschrieben, seht ihr was der Code macht. Wir erstellen unseren Salt mit der Funktion "random".
      Wir fügen den Salt mit dem Passwort zusammen (MD5(Salt) + MD5(Passwort)) und generieren daraus dann noch einmal den Hash. (MD5(MD5(Salt) + MD5(Passwort))
      Das Passwort welches wir mit dem Salt verschlüsselt haben Speichern wir mit dem Salt in die Datenbank.

      Wieso Speichern wir den Salt in die Datenbank? Nun, wir müssen ja auch irgendwie wieder den gleichen Salt zur Authentifizierung bekommen.


      PAWN-Quellcode

      1. if(dialogid == DIALOG_LOGIN){ if(response) { if(strlen(inputtext) > 6) { new Query[256], Salt[64], Password[128], Final[128]; mysql_format(Handle, strQuery, 256, "SELECT * FROM users WHERE username='%e' LIMIT 1", Playername(playerid)); mysql_query(Handle, strQuery); //Wir holen uns die Spalten des Users in der Datenbank cache_get_field_content(0, "password", Password, Handle, 128); //Lesen das Gesaltete Passwort aus cache_get_field_content(0, "salt", Salt, Handle, 64); //Lesen unseren Salt aus format(Final, 128, "%s%s", Salt, MD5_Hash(inputtext)); //Fügen unser Salt aus der Datenbank mit dem Passwort vom inputtext zusammen format(Final, 128, "%s", MD5_Hash(Final)); //Hashen es ingesammt if(!strcmp(Password, Final)) { /* Wir haben unser Inputtext mit dem Salt aus der Datenbank zusammen gefügt und Gehasht. Nun sollten wir eigentlich den gleichen Hash bekommen der als "Passwort" in der Datenbank steht. Unser Passwort wird sozusagen garnicht erst abgespeichert sondern komplett gehasht. */ } } else { SendClientMessage(playerid, -1, "Passwort muss mindestens 6. Zeichen lang sein!"); } } else { Kick(playerid); }}


      Wir erstellen in dieser Funktion mit unserem Salt aus der Datenbank und unser Inputtext unser Hash der schon in der Datenbank als "Passwort" steht.
      Dadurch das der Salt abgespeichert wurde, können wir diesen Verwenden um das gleiche Endprodukt zu bekommen, welches wir bei der Registration hatten. (Das Passwort)
      Mit diesem Hash machen wir nun den abgleich ob der selbe auch genau in der Datenbank steht. Tut er es, können wir uns erfolgreich einloggen.


      Ich hoffe euch hat das kurze Tutorial gefallen, man sollte es mit etwas Wissen auch ohne Probleme verstehen.
      Bitte lass mir doch ein Feedback da, was ich besser machen kann, und wenn ihr Fragen habt, stellt sie einfach.


      liebe grüße Grab ;)

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Warren ()

    • Darf ich dir 2 gute Tipps geben ?

      1. strlen(inputtext) > 6 kann man auch easy optimieren inputtext[0] != EOS

      2. Wenn ich sowas sehe bekomme ich das kotzen VORSICHT Memoryleak, leider kennt das MySQL Plugin sowas wie ein garbagecollector nicht.


      Quellcode

      1. mysql_format(Handle, strQuery, 256, "SELECT * FROM users WHERE username='%e' LIMIT 1", Playername(playerid));
      2. mysql_query(Handle, strQuery); //Wir holen uns die Spalten des Users in der Datenbank
      3. cache_get_field_content(0, "password", Password, Handle, 128); //Lesen das Gesaltete Passwort aus
      4. cache_get_field_content(0, "salt", Salt, Handle, 64); //Lesen unseren Salt aus
      zu


      Quellcode

      1. mysql_format(Handle, strQuery, 256, "SELECT * FROM users WHERE username='%e' LIMIT 1", Playername(playerid));
      2. new Cache:result = mysql_query(Handle, strQuery); //Wir holen uns die Spalten des Users in der Datenbank
      3. cache_get_field_content(0, "password", Password, Handle, 128); //Lesen das Gesaltete Passwort aus
      4. cache_get_field_content(0, "salt", Salt, Handle, 64); //Lesen unseren Salt aus+
      5. cache_delete(result);

      siehe auch

      wiki.sa-mp.com/wiki/MySQL/R33#mysql_query
    • IPrototypeI schrieb:

      Darf ich dir 2 gute Tipps geben ?

      1. strlen(inputtext) > 6 kann man auch easy optimieren inputtext[0] != EOS

      2. Wenn ich sowas sehe bekomme ich das kotzen VORSICHT Memoryleak, leider kennt das MySQL Plugin sowas wie ein garbagecollector nicht.


      Quellcode

      1. mysql_format(Handle, strQuery, 256, "SELECT * FROM users WHERE username='%e' LIMIT 1", Playername(playerid));
      2. mysql_query(Handle, strQuery); //Wir holen uns die Spalten des Users in der Datenbank
      3. cache_get_field_content(0, "password", Password, Handle, 128); //Lesen das Gesaltete Passwort aus
      4. cache_get_field_content(0, "salt", Salt, Handle, 64); //Lesen unseren Salt aus
      zu


      Quellcode

      1. mysql_format(Handle, strQuery, 256, "SELECT * FROM users WHERE username='%e' LIMIT 1", Playername(playerid));
      2. new Cache:result = mysql_query(Handle, strQuery); //Wir holen uns die Spalten des Users in der Datenbank
      3. cache_get_field_content(0, "password", Password, Handle, 128); //Lesen das Gesaltete Passwort aus
      4. cache_get_field_content(0, "salt", Salt, Handle, 64); //Lesen unseren Salt aus+
      5. cache_delete(result);
      siehe auch

      wiki.sa-mp.com/wiki/MySQL/R33#mysql_query

      Daran hatte ich ja garnicht gedacht. ;) Dachte das ist mit neuen Pluginupdates selbstverständlich geworden. Aber, gut zu wissen.


      @Jony:
      Du meinst also das es nichts bringt? Möchtest du also bei einem Dump komplette Userdaten an die Öffentlichtkeit geben?
    • Dev_Grab schrieb:

      IPrototypeI schrieb:

      Darf ich dir 2 gute Tipps geben ?

      1. strlen(inputtext) > 6 kann man auch easy optimieren inputtext[0] != EOS

      2. Wenn ich sowas sehe bekomme ich das kotzen VORSICHT Memoryleak, leider kennt das MySQL Plugin sowas wie ein garbagecollector nicht.


      Quellcode

      1. mysql_format(Handle, strQuery, 256, "SELECT * FROM users WHERE username='%e' LIMIT 1", Playername(playerid));
      2. mysql_query(Handle, strQuery); //Wir holen uns die Spalten des Users in der Datenbank
      3. cache_get_field_content(0, "password", Password, Handle, 128); //Lesen das Gesaltete Passwort aus
      4. cache_get_field_content(0, "salt", Salt, Handle, 64); //Lesen unseren Salt aus
      zu


      Quellcode

      1. mysql_format(Handle, strQuery, 256, "SELECT * FROM users WHERE username='%e' LIMIT 1", Playername(playerid));
      2. new Cache:result = mysql_query(Handle, strQuery); //Wir holen uns die Spalten des Users in der Datenbank
      3. cache_get_field_content(0, "password", Password, Handle, 128); //Lesen das Gesaltete Passwort aus
      4. cache_get_field_content(0, "salt", Salt, Handle, 64); //Lesen unseren Salt aus+
      5. cache_delete(result);
      siehe auch

      wiki.sa-mp.com/wiki/MySQL/R33#mysql_query
      Daran hatte ich ja garnicht gedacht. ;) Dachte das ist mit neuen Pluginupdates selbstverständlich geworden. Aber, gut zu wissen.


      @Jony:
      Du meinst also das es nichts bringt? Möchtest du also bei einem Dump komplette Userdaten an die Öffentlichtkeit geben?
      Das man Passwörter nicht im Klartext speichern sollte, steht außer Frage. Aber ich wollte damit deutlich machen, das letzendlich wichtig ist, die DB-Server richtig abzusichern, als Passwörter kompliziert und komplett sinnfrei zu hashen/salten. Im Normalfall reicht es, ein Passwort welches MD5/sha1, etc. ist, mit einem persönlichem Salt zu versehen.
      Man darf ebenfalls nicht vergessen, das die Normalen und gängigen Methoden wie MD5/sha1 lächerlich sind, und man gleich seine Passwörter im Klartext abspeichern kann. Es gibt hier gute Möglichkeiten Passwörter zu cracken.

      Zum Nachlesen hier.
      Wichtig als Fazit ist folgendes:


      suit.rebell.at schrieb:

      Hinweise zum Schluß
      Die genannten Methoden sind zum Schutz von größeren Datenbeständen gedacht und stellen wie beschrieben nur eine Verkomplizierung für den Angreifer darf. Keineswegs ersetzen Sie aber ein entsprechendes Sicherheitskonzept für den Datenbestand bzw. eine entsprechende Sorgfalt im Umgang mit den Daten.
      Ein einzelnes, schlecht gewähltes Passwort lässt sich auch durch die beschriebenen Techniken nicht entsprechend schützen. Ebenso lässt sich von außen idR. nicht beurteilen, wie gut der Diensteanbieter die Nutzerdaten sichert bzw. ob er dies überhaupt tut. Aus diesem Grund ist es empfehlenswert möglichst überall ein anderes Passwort zu verwenden.

      Ich möchte persönlich hier nochmal hinzufügen, dass wenn man im sog. "Darknet" unterwegs ist, man viele Dumps von Projekte, Webseiten etc. findet. Fakt ist einfach, hat man erstmal die Datenbank, ist alles andere sehr schnell erledigt. Und hier liegt der Teufel einfach im Detail, dass der dreh' und Angelpunkt eben der DB-Server ist und die Programmierung der Anwendung. (SQL-Injections, etc.)
      Ebenfalls möchte @Dev_Grab nochmals anmerken, dass ich das Tutorial an sich ja wirklich in Ordnung geht, aber ich für meinen Teil hätte erwartet hier ebenfalls auf die Aspekte der Datenbehandlung und Datensicherheit einzugehen. Es ist eben nicht nur mit einem "sicheren Passwort" erledigt.
      Das einiges auch von den Passwörterauswahl des Users abhängt, sollte natürlich klar sein. Aber das lass ich mal außen vor.

      //edit:
      Abgeändert.
      Chief Technology Officer (CTO)
      www.rage-multiplayer.de

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Jony ()

    • @John:

      Stimmt schon, das Tutorial sollte aber generell um das Salten von Passwörtern gehen.

      Natürlich sollte es jedem normalen Scripter bewusst sein, das man sichere Passwörter für solch Sachen verwendet.
      Aber man kann es ja dann noch später ausbauen, viele verstehen den Sinn hinter "Sicherheit" dann nicht.
    • KazutoSensei schrieb:

      Ich bin ganz ehrlich, aber irgendwie blicke ich nicht ganz durch, dein Code sieht bei mir so durcheinander aus und über 75% auskommentiert.
      Ich würde eine Überarbeitung super finden, außer ich bin der einzige der das sieht bzw so sieht. Aufjedenfall kann ich noch keine Bwertung geben.

      lg
      Der Code war mal formatiert. Ist aber aus irgendeinen Grund durcheinander geraten.