Verschlüsselung Datenbankfelder


nchristoph

Erfahrenes Mitglied
Hallo Zusammen,

Ich werkle gerade an einer Webseite und habe da die "Blödsinninge" Idee, die Datenbankfelder zu verschlüsseln.

Ich habe schon mit hash versucht, aber die kann man ja nur vergleichen und nicht entschlüsseln und daher für Abfragen mit WHERE Klausel nicht verwendbar.
Dann habe ich noch OpenSSL Verschlüsselung versucht nur da wird empfohlen, nie den gleichen IV doppelt zu verwenden, was das entschlüsseln bzw. WHERE Klauseln sehr schwer macht.

Passwörter habe ich bereits mit Password_hash und BCRYPT gespeichert.

Wir würdet Ihr da dran gehen?

Ob es sinnvoll ist oder nicht sei dahingestellt ist auch nicht das Thema.
 

Sprint

Erfahrenes Mitglied
Sinnvoll ist es wirklich nicht, denn so einfach mal suchen in der DB fällt damit natürlich weg. Aber gut.

Ich habe das hier für mein letztes Projekt genutzt. Da ging es zwar mehr um die Verschlüsselung von Dateien, aber sowohl die Datei als auch das jeweils kundenspezifische Kennwort wurden mit diesem Script verschlüsselt.

Wie auch immer du das handhabst, wirst du nicht um Kennwörter in Klarschrift rumkommen. Du kannst die natürlich auch wieder mit einem Masterkey verschlüsseln, aber der muß in Klarschrift vorliegen. Ich habe den damals per ionCube verpacken lassen, so daß auch bei einem direkten Zugriff auf die Datei niemand so schnell an den Masterkey kommt.

Eine weitere Möglichkeit wäre noch, die Verschlüsselung der Datenbank selbst zu überlassen. Für MariaDB gibt es z.B. eine solche Erweiterung. Ob das von deinem Provider aber schon angeboten bzw. unterstützt wird, ist im Moment noch fraglich.
 

Sprint

Erfahrenes Mitglied
Nein, das stimmt nicht. Deswegen gibt es ja gerade "password hashing".
Was das Speichern von Login Passwörtern geht, hast du recht. Und wenn nur der jeweilige User auf seine eigenen Daten zugreift, dann ginge es, wenn das beim Login eingegebene PW dann zum Entschlüsseln der anderen Daten verwendet wird. Sollen die Daten aber ohne den jeweiligen User bzw. ganz ohne einen menschlichen Zugriff verarbeitet werden, braucht es einen Master Schlüssel in Klarschrift. Aber dazu bräuchte es mehr Infos über den Hintergrund der Anfrage.
 

ComFreek

Mod | @comfreek
Moderator
@Sprint Wieso sollte man das Nutzer-PW für die Ver/Entschlüsselung von den Nutzerdaten hernehmen? Warum nicht einfach einen (kryptographisch starken) zufälligen Key wählen?
 

Sprint

Erfahrenes Mitglied
@Sprint Wieso sollte man das Nutzer-PW für die Ver/Entschlüsselung von den Nutzerdaten hernehmen? Warum nicht einfach einen (kryptographisch starken) zufälligen Key wählen?
Die Verschlüsselung von Tabellenfeldern macht mMn ja nur Sinn, wenn jemand direkten Zugriff auf die Datenbank hat. Jedes Anwenderprogramm muß die Daten ja entschlüsselt vorliegen haben. Wer also Zugriff auf die Anwendung hat, bekommt die Daten frei geliefert.

Wo aber wird der zufällige Schlüssel abgelegt? Egal ob in der Datenbank oder in einer Datei, er liegt immer in Klarschrift vor. Und aus der Struktur oder Feldnamen einer Tabelle läßt sich schon mehr oder weniger leicht das Feld mit dem Kennwort herausfinden. Wenn ich jetzt aber das Nutzerkennwort hernehme, lassen sich die Felder nicht entschlüsseln, weil ich nicht an das echte Kennwort komme. Denn aus einem Hash läßt sich das nicht rausrechnen.
 

nchristoph

Erfahrenes Mitglied
@ComFreek
Schützen will ich eigentlich nur die Daten für den Fall, das jemand an die Datenbank kommt.
Das ich vorher noch einige Layer brauche, die den Zugriff verhindern bzw. zumindest stark vermehren ist mir bewusst.

@Sprint
An das Passwort als IV bzw. Schlüssel habe ich natürlich auch gedacht ABER was ist, wenn der Benutzer sein Passwort ändert. Reintheoretisch müsste ich alles mit dem alten PW auslesen und entschlüsseln und mit dem neuen wieder verschlüsseln und in die Datenbank speichern. Ist nicht gerade Effizient. Dein Link ist auch das, was ich schon probiert habe nur wie du bereits gesagt hast ist dann Sense mit einfacher DB Arbeit.

Da es auch um PM's geht, die der Empfänger lesen können soll, müsste es fast so was wie Private und Public key alá RSA sein nur da wüsste ich nicht, wie ich das mit PHP umsetzen sollte.

Eine andere Idee, die ich noch habe ist das MySQL Native AES_ENCRPYT /AES_DECRYPT.

Ist ein ziemlich umfangreiches Thema, wenn man es 99,9% sicher haben will.

Aktuell habe ich folgende Sicherheitsvorkehrungen

HTTPS(Besser als gar nichts)
MySQL Verschlüsselung mit SSL verschlüsselt(Ich weis, eher Sinnfrei weil die Kommunikation beim selben Server über einen Socket geht und nur sinnvoll bei externen Servern wirklich sinnvoll ist)

PHP mässig:

Jede ID wird mittels intval geprüft und zusätzlich noch durch Filter_var und Striptags gefiltert und bereinigt.
Für die Datenbankabfragen habe ich Prepared statements bzw. Myslqi_Real_Escape_String im Einsatz.
Das Passwort wird gesaltet und dann mit password_hash gehasht.

Das ist so ziemlich alles, was mir einfällt was ich machen kann zum Absichern.

Vielleicht hat hier der eine oder andere auch noch ein paar Tips.
 

ComFreek

Mod | @comfreek
Moderator
und zusätzlich noch durch Filter_var und Striptags gefiltert und bereinigt.
Alles nach intval ist unnötig. intval liefert immer ein int zurück, was möchtest du da noch tun?

Das Passwort wird gesaltet und dann mit password_hash gehasht.
Ist dein Salt user-spezifisch?

Schützen will ich eigentlich nur die Daten für den Fall, das jemand an die Datenbank kommt.
Meinst du, dass jemand SQL Queries ausführen kann? Falls ja, kannst du auch mal dir Pepper ansehen: Pepper (cryptography) - Wikipedia.
 

Sprint

Erfahrenes Mitglied
An das Passwort als IV bzw. Schlüssel habe ich natürlich auch gedacht ABER was ist, wenn der Benutzer sein Passwort ändert. Reintheoretisch müsste ich alles mit dem alten PW auslesen und entschlüsseln und mit dem neuen wieder verschlüsseln und in die Datenbank speichern. Ist nicht gerade Effizient.
Das ist richtig, aber wie oft kommt das vor? Ich habe sowas ähnliches auch schon mal machen müssen, als ich die PW Verschlüsselung selbst geändert hatte. Ist von Aufwand her gering und wird von der zeitlichen Seite her wahrscheinlich gar nicht bemerkt. Und es müssen ja auch nicht alle Daten verschlüsselt werden.

Andererseits müssen wir doch mal überlegen, wie jemand an einen DB Dump kommt. Da die ja hoffentlich nicht so offen auf deinem Webspace rumliegen, muß er die Zugangsdaten zu deinem Serverlogin haben. Und dann hast du ein ganz anderes Problem. Denn dann kommt er auch an deine PHP Dateien und kann die in aller Ruhe zerlegen und analysieren. Eventuelle Pepper oder OpenSSL Kennwörter liegen da ja auch irgendwo offen im Quelltext rum. Eine Verschlüsselung mit ionCube macht das zumindest deutlich schwerer.

Viel eher ist meiner Ansicht nach ein Einbruch über unsichere Formulare oder vergessene Testprogramme usw. Ich würde eher da ansetzen und sicherstellen, daß da nichts passieren kann bzw. über geklaute Zugangsdaten eines Users nur dessen Daten abgegriffen werden können.

Bzgl. DB würde ich eher mal nachsehen, was für einen Typ Datenbank du hast und dann mal suchen, ob es dafür eine DB eigene Verschlüsselung gibt. Sprich dann mal mit deinem Provider, ob man die installieren kann.
 

nchristoph

Erfahrenes Mitglied
Ich z.b. ändere 3 - 4 x im Jahr alle meine Passwörter.

Zurück zum Thema:

Wie meinst du über unsichere Formulare? $_POST Variablen nicht gefiltert?
 

nchristoph

Erfahrenes Mitglied
Ok, das mach ich Überall, werd da aber den Code nochmal extra durchchecken.

Was ich eher meinte ist, für den Fall das jemand die Datenbank in die Finger bekommt.

Mein Ansatz für den OpenSSL Key wäre gewesen, den Key ausserhalb des /var/html Verzeichnisses zu speichern und den IV als hash in der Datenbank zu speichern.

Password_hash ist ja Oneway. Es ist nur ein True or False Vergleich mittels hash_verify möglich.
Einen generellen IV will ich nicht setzen und das Password als IV zu setzen ist mir nach momentanen Stand der Dinge zuviel Aufwand. Vor allem, da ich ja bei jeder Passwortänderung, und es gibt ja ab und an noch Leute, die Ihr Passwort regelmässig ändern, den Inhalt eines jeden Feldes ent- und wieder verschlüsseln muss.

Muss zwar nur einmal programmiert werden, muss halt bombenfest sein und dafür fehlt mir momentan die Routine um das 100% hinzubekommen.

Als andere Idee hätte ich gehabt, den IV random zu generieren und die IV's in einer seperaten DB zu speichern. nur hätten ich da wieder eine zusätzliche Verbindung und Resourcen verballert.

Irgendwie ist das Thema zu gross für mich habe ich so das Gefühl, weil es ja soviele Möglichkeiten und Varianten gibt.
 
Zuletzt bearbeitet:

ComFreek

Mod | @comfreek
Moderator
Irgendwie ist das Thema zu gross für mich habe ich so das Gefühl, weil es ja soviele Möglichkeiten und Varianten gibt.
Das kann ich verstehen, aus dem Grund bin ich auch sehr vorsichtig, sichere Maßnahmen vorzuschlagen. (Andersrum aber merke ich unsichere Maßnahmen direkt hier im Forum an, falls ich sie sehe und entdecke ;))

Zu deinen Ideen im aktuellen Beitrag kann ich deswegen leider nichts beisteuern.

Im Zweifel mal auf Information Security Stack Exchange suchen und/oder fragen.
 

nchristoph

Erfahrenes Mitglied
Kein Problem.

Anders gefragt:

Ich programmiere es mal jetzt mal testhalber so:

Der Private Key wird zusammen mit der Account ID in DB2 gespeichert

Sobald 2 Personen sich gegenseitig sich z.b. eine PM schicken, wird der jeweilige Publickey mit dem Privatekey des anderen verschlüsselt und in der Datenbank mit Semikolon getrennt gespeichert.

PrivateKey und Publickey sind jeweils Key und IV für OpenSSL_encrypt und decrypt.

Die einzelnen Felder werden so OpenSSL mässig verschlüsselt und sollte jemand an die DB kommen, sieht er nur verschlüsseltes Kauderwelsch.

Ist jetzt nur ein Gehirngespenst und ich bin auch noch am austüfteln der Details, aber ich denke, so könntedas alles ziemlich sicher sein oder?
 

StormChaser

Mitglied
Hallo Zusammen,

Ich werkle gerade an einer Webseite und habe da die "Blödsinninge" Idee, die Datenbankfelder zu verschlüsseln.

Ich habe schon mit hash versucht, aber die kann man ja nur vergleichen und nicht entschlüsseln und daher für Abfragen mit WHERE Klausel nicht verwendbar.
Dann habe ich noch OpenSSL Verschlüsselung versucht nur da wird empfohlen, nie den gleichen IV doppelt zu verwenden, was das entschlüsseln bzw. WHERE Klauseln sehr schwer macht.

Passwörter habe ich bereits mit Password_hash und BCRYPT gespeichert.

Wir würdet Ihr da dran gehen?

Ob es sinnvoll ist oder nicht sei dahingestellt ist auch nicht das Thema.
Vorweg: Der letzte Satz gefällt mir sehr gut; ist auch meistens mein Credo :)

Zum Problem:
Es sind 2 mögliche Szenarien:
1. Es werden die Datensätze geladen, die über einen (Primary) Key identifiziert werden.
2. Es sollen Datensätze geladen werden, bei denen bestimmte Teil-Feldinhalte bestimmte Kriterien erfüllen.

Dass sich im ersten Fall problemlos jede Art von Verschlüsselung auf die Inhalte anwenden lässt, dürfte klar sein.

Sollen im zweiten Fall beispielsweise Datensätze geladen werden, bei denen Spalte X die Zeichenfolge
"Yippie Yah Yei Schweinebacke!"
enthält, dann ist es - mit einer Ausnahme* - eigentlich nicht möglich, Verschlüsselung anzuwenden, sofern der restliche Inhalt des Feldes unbekannt ist..

Um auf die Frage "Wir würdet Ihr da dran gehen?" einzugehen:
Für den ersten Fall bastele ich immer mal wieder etwas anderes.
Für den zweiten Fall überlege ich mir, ob es Inhalte gibt, die durchsucht werden müssen. Falls ja, hat sich das für mich mit Verschlüsselung erledigt. Falls nein, trifft der erste Fall zu.

* Jedes Zeichen ist mit einem bestimmten Schlüssel verschlüsselt.
 

Neue Beiträge