Wie sichere Datenbankkennwörter in PHP?

404

Wenn eine PHP-Anwendung eine Datenbankverbindung herstellt, muss sie im Allgemeinen natürlich ein Login und ein Passwort übergeben. Wenn ich für meine Anwendung ein einziges Login mit Mindestberechtigung verwende, muss das PHP dieses Login und Passwort irgendwo kennen. Was ist der beste Weg, um dieses Passwort zu sichern? Es scheint, als wäre es keine gute Idee, es nur in den PHP-Code zu schreiben.

user18359
quelle
1
Um absolut sicher zu sein, müssen Sie eine SSL-Verbindung einrichten. Andernfalls kann jeder in Ihrem Netzwerk das von Ihnen eingegebene Kennwort weiterhin abhören.
Charles Ma
1
Meinen Sie die Benutzerkennwörter oder das Datenbankkennwort, die in der Verbindungszeichenfolge verwendet werden?
Ozgur Ozcitak
4
In der Verbindungszeichenfolge verwendetes Datenbankkennwort. Vielen Dank!
user18359

Antworten:

238

Einige Leute haben dies als Frage zum Speichern von Passwörtern in einer Datenbank falsch verstanden . Das ist falsch. Hier geht es darum, wie Sie das Kennwort speichern, mit dem Sie zur Datenbank gelangen.

Die übliche Lösung besteht darin, das Passwort aus dem Quellcode in eine Konfigurationsdatei zu verschieben. Überlassen Sie dann die Verwaltung und Sicherung dieser Konfigurationsdatei Ihren Systemadministratoren. Auf diese Weise müssen Entwickler nichts über die Produktionskennwörter wissen, und es gibt keine Aufzeichnung des Kennworts in Ihrer Quellcodeverwaltung.

user11318
quelle
8
Vielen Dank. Wenn ich das richtig verstehe, hat die PHP-Datei ein Include in der Konfigurationsdatei, so dass sie das Passwort verwenden kann. Beispiel: Ich erstelle eine Datei mit dem Namen 'app1_db_cfg.php', in der Login, Pword und DB-Name gespeichert sind. Dann enthält meine application.php-Seite 'app1_db_cfg.php' und ich bin im Geschäft!
user18359
28
Ich bin damit einverstanden, dass die Konfiguration ordnungsgemäß geschützt werden muss. Zu wissen, wie das geht, ist jedoch Sache der Systemadministratoren, nicht der Entwickler. Ich bin nicht einverstanden mit dem Wert einer starken Verschlüsselung in diesem Fall. Wenn Sie Ihre Konfigurationsdatei nicht schützen können, warum glauben Sie dann, dass Sie Ihre Schlüssel schützen können?
user11318
10
Ich bevorzuge die Verwendung eines Datenbankkontos, das nur vom Webserver aus auf die Datenbank zugreifen darf. Und dann mache ich mir nicht die Mühe, die Konfiguration zu verschlüsseln, sondern speichere sie einfach außerhalb des Webstamms.
Gnud
11
Ich verwende eine Apache-Umgebungsvariable, um den Pfad so festzulegen, dass selbst der Pfad zur Datei im Quellcode unbekannt ist. Dies ermöglicht auch ein anderes Passwort für Entwicklung und Produktion, basierend auf den Apache-Einstellungen auf dem Server
geedew
15
Beachten Sie bitte, dass auch Dateien, die außerhalb des über das Internet zugänglichen Verzeichnisses gespeichert sind, von dem Skript gelesen werden müssen, das sie verwendet. Wenn jemand diese Datei einschließt und dann die Daten aus der Datei ausgibt, wird das Kennwort angezeigt.
Rick Mac Gillis
104

Wenn Sie auf einem anderen Server hosten und keinen Zugriff außerhalb Ihrer Webroot haben, können Sie Ihr Kennwort und / oder Ihre Datenbankverbindung jederzeit in eine Datei einfügen und die Datei dann mit einem .htaccess sperren:

<files mypasswdfile>
order allow,deny
deny from all
</files>
kellen
quelle
3
Danke, genau das habe ich gesucht.
David Gladfelter
28
Auf jeden Fall, aber wenn jemand Shell-Zugriff hat, wurde Ihr gesamtes Konto trotzdem kompromittiert.
Kellen
4
Dies ist eine schlechte Vorgehensweise, da Sie Ihre Anmeldeinformationen möglicherweise versehentlich in ein Repository übertragen.
Porlune
2
@Ankit: Wenn es einem Nicht-Benutzer möglich ist, eine Datei auf den Server hochzuladen und auszuführen, ist der Server nicht richtig konfiguriert.
Kellen
6
@Porlune: Entwickler sollten ihr Versionskontrollsystem dazu bringen, die Kennwortdatei zu ignorieren, dh einen .gitignore zu verwenden. Aber ja, bei Dateien, die vertrauliche Daten enthalten, ist Vorsicht geboten.
Kellen
45

Am sichersten ist es, die in Ihrem PHP-Code angegebenen Informationen überhaupt nicht zu haben.

Wenn Sie Apache verwenden, bedeutet dies, dass Sie die Verbindungsdetails in Ihrer httpd.conf- oder virtuellen Hosts-Dateidatei festlegen. Wenn Sie dies tun, können Sie mysql_connect () ohne Parameter aufrufen, was bedeutet, dass PHP Ihre Informationen niemals ausgeben wird.

So geben Sie diese Werte in diesen Dateien an:

php_value mysql.default.user      myusername
php_value mysql.default.password  mypassword
php_value mysql.default.host      server

Dann öffnen Sie Ihre MySQL-Verbindung wie folgt:

<?php
$db = mysqli_connect();

Oder so:

<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
                     ini_get("mysql.default.password"),
                     ini_get("mysql.default.host"));
Lars Nyström
quelle
1
Bitte überprüfen Sie die korrekten Werte von ini_get ('Standardwerte') php.net/manual/en/class.mysqli.php
Val
4
Ja, aber jeder Benutzer (oder ein Hacker, der schlecht geschriebenes PHP-Skript missbraucht) kann das Passwort über lesen ini_get().
Marki555
1
@ Marki555 but any user (or a hacker abusing badly written php script) can read the password via ini_get()Wie gehst du damit um?
Tonix
2
Marki555 sagt, dass ein Angreifer, der PHP-Code ausführen kann, auch PHP-Funktionen aufrufen kann, was offensichtlich wahr und unmöglich ist, etwas dagegen zu tun. Ich möchte auch hinzufügen, dass ich den Ratschlägen, die ich in dieser Antwort gebe, nicht mehr selbst folge, sondern Umgebungsvariablen verwende. Das Konzept ist jedoch ähnlich: Speichern Sie Ihre Anmeldeinformationen nicht im Code, sondern fügen Sie sie irgendwie ein. Es ist nicht wirklich wichtig, ob Sie ini_get()oder verwenden getenv().
Lars Nyström
2
@DeepBlue Wenn Sie ini_get () injizieren können, können Sie auch file_get_contents (anypath) injizieren. Solange PHP eine Möglichkeit hat, an das Passwort zu gelangen, wird auch jeder schädliche Code verwendet.
Varesa
40

Speichern Sie sie in einer Datei außerhalb des Webstamms.

da5id
quelle
29
Und auch, wie an anderer Stelle erwähnt, außerhalb der Quellcodeverwaltung.
Frank Farmer
6
könnten wir es aufnehmen? zB in PHP können wir dann tun include('../otherDirectory/configfile.conf')?
MTK
1
Sie schlagen alle vor, Anmeldeinformationen außerhalb von wwwroot zu speichern. Ok, ich verstehe den Sicherheitshintergrund. Aber wie soll es dann in der Versionskontrolle gespeichert werden (Beispielkonfiguration)? Normalerweise ist wwwroot die Wurzel von Git Repo. Wenn sich also etwas außerhalb befindet, befindet es sich außerhalb von VC. Stellen Sie sich einen neuen Entwickler vor, der versucht, eine lokale Instanz für die Entwicklung einzurichten. Woher sollte er Magie wie "Nehmen Sie diese Datei, kopieren Sie sie nach draußen und füllen Sie sie aus" kennen?
Der Pate
@TheGodfather Die Idee ist, dass ein neuer Entwickler seine eigenen Anmeldeinformationen für seine eigene Entwicklungsumgebung haben sollte. Es ist zwar eine gute Praxis, eine Readme-Datei mit Anweisungen oder Kommentaren im Code zu haben, die angeben, wie Sie sie konfigurieren sollen (aber nicht die tatsächlichen Daten).
PhoneixS
@ TheGodfather, Readme-Datei?
Pacerier
35

Für extrem sichere Systeme verschlüsseln wir das Datenbankkennwort in einer Konfigurationsdatei (die selbst vom Systemadministrator gesichert wird). Beim Start der Anwendung / des Servers fordert die Anwendung den Systemadministrator zur Eingabe des Entschlüsselungsschlüssels auf. Das Datenbankkennwort wird dann aus der Konfigurationsdatei gelesen, entschlüsselt und zur zukünftigen Verwendung im Speicher gespeichert. Immer noch nicht 100% sicher, da es entschlüsselt im Speicher gespeichert ist, aber Sie müssen es irgendwann als "sicher genug" bezeichnen!

pdavis
quelle
85
Was ist, wenn der Administrator stirbt?
Radu Murzea
36
@ RaduMurzea das ist lächerlich. Wann haben Sie von Sys Admins im Sterben gehört? Sie sind wie McDonalds, sie erscheinen / verschwinden einfach aus dem Nichts!
ILikeTacos
13
@ Radu Murzea Habe nur 2 oder mehr Admins, dann hast du Parität wie ein Raid-Array. Die Wahrscheinlichkeit, dass mehr als ein Laufwerk gleichzeitig ausfällt, ist viel geringer.
Element11
5
Was ist, wenn die Server neu gestartet werden? Was ist mit der Zeit, die benötigt wird, um den Administrator zu aktivieren, damit er das Kennwort in..etc.etc eingibt? lol
John Hunt
1
Ich bin mir nicht sicher, was Sie unter "im Speicher gespeichert" verstehen. PHP-Webanwendungen speichern im Allgemeinen nichts länger im Speicher als die Zeit, die benötigt wird, um auf eine einzelne Anfrage zum Anzeigen einer Seite zu antworten.
BDSL
15

Diese Lösung ist insofern allgemein, als sie sowohl für Open- als auch für Closed-Source-Anwendungen nützlich ist.

  1. Erstellen Sie einen Betriebssystembenutzer für Ihre Anwendung. Siehe http://en.wikipedia.org/wiki/Principle_of_least_privilege
  2. Erstellen Sie für diesen Benutzer eine (Nicht-Sitzungs-) Betriebssystemumgebungsvariable mit dem Kennwort
  3. Führen Sie die Anwendung als dieser Benutzer aus

Vorteile:

  1. Sie werden Ihre Passwörter nicht versehentlich in die Quellcodeverwaltung einchecken, weil Sie dies nicht können
  2. Sie werden die Dateiberechtigungen nicht versehentlich vermasseln. Nun, Sie könnten, aber es wird dies nicht beeinflussen.
  3. Kann nur von root oder diesem Benutzer gelesen werden. Root kann sowieso alle Ihre Dateien und Verschlüsselungsschlüssel lesen.
  4. Wie speichern Sie den Schlüssel sicher, wenn Sie Verschlüsselung verwenden?
  5. Funktioniert x-Plattform
  6. Stellen Sie sicher, dass die envvar nicht an nicht vertrauenswürdige untergeordnete Prozesse übergeben wird

Diese Methode wird von Heroku vorgeschlagen, die sehr erfolgreich sind.

Neil McGuigan
quelle
11

Wenn es möglich ist, die Datenbankverbindung in derselben Datei zu erstellen, in der die Anmeldeinformationen gespeichert sind. Fügen Sie die Anmeldeinformationen in die connect-Anweisung ein.

mysql_connect("localhost", "me", "mypass");

Andernfalls ist es am besten, die Anmeldeinformationen nach der connect-Anweisung zu deaktivieren, da Anmeldeinformationen, die sich nicht im Speicher befinden, nicht aus dem Speicher gelesen werden können ;)

include("/outside-webroot/db_settings.php");  
mysql_connect("localhost", $db_user, $db_pass);  
unset ($db_user, $db_pass);  
Bob Fanger
quelle
9
Wenn jemand Zugriff auf den Speicher hat, sind Sie trotzdem geschraubt. Das ist sinnlose Fälschungssicherheit. Außerhalb der Webroot (oder zumindest durch einen .htaccess geschützt, wenn Sie keinen Zugriff über Ihre Webroot haben) ist die einzig sichere Option.
uliwitness
2
@uliwitness - Das ist so, als würde man sagen, nur weil jemand das Schloss Ihres Netzwerkbetriebszentrums mit einer Acetylenlampe durchschneiden kann, bedeutet dies, dass die Tür auch eine gefälschte Sicherheit ist. Es ist immer sinnvoll, vertrauliche Informationen so eng wie möglich zu halten.
Luke A. Leber
1
Wie wäre es mit echo $ db_user oder dem Drucken des $ db_pass? Selbst Entwickler im selben Team sollten nicht in der Lage sein, die Produktionsanmeldeinformationen herauszufinden. Der Code sollte nichts Druckbares über die Anmeldeinformationen enthalten.
Mohammed Joraid
8

Ihre Auswahlmöglichkeiten sind begrenzt, da Sie das Kennwort für den Zugriff auf die Datenbank benötigen. Ein allgemeiner Ansatz besteht darin, den Benutzernamen und das Kennwort in einer separaten Konfigurationsdatei und nicht im Hauptskript zu speichern. Stellen Sie dann sicher, dass Sie das außerhalb des Hauptwebbaums speichern. Wenn es ein Problem mit der Webkonfiguration gibt, bei dem Ihre PHP-Dateien einfach als Text angezeigt und nicht ausgeführt werden, haben Sie das Kennwort nicht offengelegt.

Ansonsten sind Sie mit minimalem Zugriff auf das verwendete Konto in der richtigen Linie. Dazu noch etwas

  • Verwenden Sie die Kombination aus Benutzername und Passwort für nichts anderes
  • Konfigurieren Sie den Datenbankserver so, dass nur Verbindungen vom Webhost für diesen Benutzer akzeptiert werden (localhost ist sogar noch besser, wenn sich die Datenbank auf demselben Computer befindet) Maschine.
  • Verschleiern Sie das Passwort (selbst ROT13 reicht aus), es wird nicht viel Schutz bieten, wenn einige Zugriff auf die Datei erhalten, aber es verhindert zumindest das gelegentliche Anzeigen.

Peter

Vagnerr
quelle
8

Wenn Sie PostgreSQL verwenden, sucht es ~/.pgpassautomatisch nach Passwörtern. Weitere Informationen finden Sie im Handbuch .

Jim
quelle
8

Zuvor haben wir DB-Benutzer / Pass in einer Konfigurationsdatei gespeichert, sind jedoch seitdem in den paranoiden Modus übergegangen - und haben eine Richtlinie zur Tiefenverteidigung übernommen .

Wenn Ihre Anwendung gefährdet ist, hat der Benutzer Lesezugriff auf Ihre Konfigurationsdatei, sodass ein Cracker diese Informationen möglicherweise lesen kann. Konfigurationsdateien können auch von der Versionskontrolle erfasst oder auf Servern kopiert werden.

Wir haben auf das Speichern von Benutzer- / Pass-Umgebungsvariablen umgestellt, die im Apache VirtualHost festgelegt wurden. Diese Konfiguration kann nur von root gelesen werden - hoffentlich wird Ihr Apache-Benutzer nicht als root ausgeführt.

Der Nachteil dabei ist, dass sich das Passwort jetzt in einer globalen PHP-Variablen befindet.

Um dieses Risiko zu minimieren, haben wir die folgenden Vorsichtsmaßnahmen:

  • Das Passwort ist verschlüsselt. Wir erweitern die PDO-Klasse um Logik zum Entschlüsseln des Passworts. Wenn jemand den Code liest, mit dem wir eine Verbindung herstellen, ist es nicht offensichtlich, dass die Verbindung mit einem verschlüsselten Kennwort und nicht mit dem Kennwort selbst hergestellt wird.
  • Das verschlüsselte Kennwort wird von den globalen Variablen in eine private Variable verschoben. Die Anwendung führt dies sofort aus, um das Fenster zu verkleinern, in dem der Wert im globalen Bereich verfügbar ist.
  • phpinfo()ist behindert. PHPInfo ist ein einfaches Ziel, um einen Überblick über alles zu erhalten, einschließlich Umgebungsvariablen.
Courtney Miles
quelle
6

Fügen Sie das Datenbankkennwort in eine Datei ein und machen Sie es für den Benutzer, der die Dateien bereitstellt, schreibgeschützt.

Dies ist so ziemlich alles, was Sie tun können, es sei denn, Sie haben nur die Möglichkeit, dem PHP-Serverprozess den Zugriff auf die Datenbank zu ermöglichen.

Chris
quelle
5

Wenn Sie über das Datenbankkennwort sprechen, im Gegensatz zu dem Kennwort, das von einem Browser stammt, scheint die Standardpraxis darin zu bestehen, das Datenbankkennwort in einer PHP-Konfigurationsdatei auf dem Server abzulegen.

Sie müssen nur sicherstellen, dass die PHP-Datei, die das Passwort enthält, über die entsprechenden Berechtigungen verfügt. Dh es sollte nur vom Webserver und von Ihrem Benutzerkonto lesbar sein.

Jason Wadsworth
quelle
1
Leider kann die PHP-Konfigurationsdatei von phpinfo () gelesen werden, und wenn jemand ein Testskript hinterlässt, kann ein glücklicher Angreifer das Passwort lesen. Es ist wahrscheinlich am besten, das Verbindungskennwort stattdessen in einer Datei außerhalb des Webserver-Stammverzeichnisses zu belassen. Der einzige Zugriff darauf ist entweder mit einer Shell oder durch Ausführen von beliebigem Code. In diesem Szenario geht jedoch die gesamte Sicherheit verloren.
MarioVilas
5

Nur irgendwo in eine Konfigurationsdatei zu legen, ist die übliche Vorgehensweise. Stellen Sie einfach sicher, dass Sie:

  1. Datenbankzugriff von Servern außerhalb Ihres Netzwerks nicht zulassen,
  2. Achten Sie darauf, dass Sie das Kennwort nicht versehentlich den Benutzern anzeigen (in einer Fehlermeldung oder durch PHP-Dateien, die versehentlich als HTML usw. bereitgestellt werden).
Marijn
quelle
5

Wir haben es folgendermaßen gelöst:

  1. Verwenden Sie Memcache auf dem Server mit offener Verbindung von einem anderen Kennwortserver.
  2. Speichern Sie das Kennwort (oder sogar die gesamte verschlüsselte Datei password.php) sowie den Entschlüsselungsschlüssel im Memcache.
  3. Die Website ruft den Memcache-Schlüssel auf, der die Passphrase der Kennwortdatei enthält, und entschlüsselt alle Kennwörter im Speicher.
  4. Der Passwortserver sendet alle 5 Minuten eine neue verschlüsselte Passwortdatei.
  5. Wenn Sie in Ihrem Projekt verschlüsselte password.php verwenden, führen Sie eine Prüfung durch, bei der überprüft wird, ob diese Datei extern berührt oder angezeigt wurde. In diesem Fall können Sie den Speicher automatisch bereinigen und den Server für den Zugriff schließen.
Asi Azulay
quelle
4

Ein zusätzlicher Trick besteht darin, eine separate PHP-Konfigurationsdatei zu verwenden, die folgendermaßen aussieht:

<?php exit() ?>

[...]

Plain text data including password

Dies hindert Sie nicht daran, die Zugriffsregeln richtig festzulegen. Wenn Ihre Website jedoch gehackt wird, wird das Skript in der ersten Zeile durch ein "Erfordernis" oder ein "Einschließen" beendet, sodass es noch schwieriger ist, die Daten abzurufen.

Lassen Sie jedoch niemals Konfigurationsdateien in einem Verzeichnis zu, auf das über das Web zugegriffen werden kann. Sie sollten einen "Web" -Ordner haben, der Ihren Steuerungscode, CSS, Bilder und JS enthält. Das ist alles. Alles andere wird in Offline-Ordnern abgelegt.

e-satis
quelle
aber wie liest dann das PHP-Skript die in der Datei gespeicherten Anmeldeinformationen?
Christopher Mahan
3
Sie verwenden fopen () wie für eine normale Textdatei.
E-Satis
2
@ e-satis ok es wird Hacker verhindern zu tun require/ includeaber wie zu verhindern fopen?
dmnc
"Dies hindert Sie nicht daran, die Zugriffsregeln richtig festzulegen"
e-satis
@ e-satis, das ist ziemlich schlau. frage mich, warum niemand daran gedacht hatte. Immer noch anfällig für das Problem mit dem Editor-Kopieren. feross.org/cmsploit
Pacerier
4

Der beste Weg ist, das Passwort überhaupt nicht zu speichern!
Wenn Sie sich beispielsweise auf einem Windows-System befinden und eine Verbindung zu SQL Server herstellen, können Sie mithilfe der integrierten Authentifizierung eine Verbindung zur Datenbank ohne Kennwort unter Verwendung der Identität des aktuellen Prozesses herstellen.

Wenn Sie eine Verbindung mit einem Kennwort herstellen müssen, verschlüsseln Sie es zuerst mit einer starken Verschlüsselung (z. B. mit AES-256 und schützen Sie dann den Verschlüsselungsschlüssel oder verwenden Sie eine asymmetrische Verschlüsselung, und lassen Sie das Betriebssystem das Zertifikat schützen) und speichern Sie es dann in einem Konfigurationsdatei (außerhalb des Webverzeichnisses) mit starken ACLs .

AviD
quelle
3
Es macht keinen Sinn, das Passwort erneut zu verschlüsseln . Jemand, der das unverschlüsselte Passwort erhalten könnte, kann auch die Passphrase erhalten, die zum Entschlüsseln des Passworts erforderlich ist. Die Verwendung von ACLs & .htaccess ist jedoch eine gute Idee.
uliwitness
2
@uliwitness Ich denke, Sie haben möglicherweise falsch verstanden - was meinen Sie mit " erneut verschlüsseln "? Es ist nur die eine Verschlüsselung. Und Sie möchten keine Passphrasen (für den menschlichen Gebrauch) verwenden, um sie zu verschlüsseln, sondern eine starke Schlüsselverwaltung, z. B. durch das Betriebssystem geschützt, so dass ein einfacher Zugriff auf das Dateisystem keinen Zugriff auf den Schlüssel gewährt.
AviD
3
Verschlüsselung ist keine Zauberei - anstatt den AES-Schlüssel mit ACLs zu schützen, können Sie das Kennwort einfach dort speichern. Es gibt keinen Unterschied zwischen dem Zugriff auf den AES-Schlüssel oder das entschlüsselte Passwort. Die Verschlüsselung ist in diesem Zusammenhang nur Schlangenöl.
MarioVilas
@MarioVilas was? Wie gibt es keinen Unterschied, wenn das Kennwort verschlüsselt ist und der Verschlüsselungsschlüssel durch das Betriebssystem geschützt ist? Verschlüsselung ist keine Zauberei - sie komprimiert lediglich die gesamte Geheimhaltung in den kleineren Verschlüsselungsschlüssel. Kaum Snakeoil in diesem Zusammenhang ist es nur bewegt alles , was Geheimhaltung in das Betriebssystem.
AviD
6
@AviD Wie kommt es, dass das Betriebssystem den Schlüssel schützen kann, aber nicht die Daten selbst? Antwort: Es kann beide schützen, daher hilft die Verschlüsselung nicht wirklich. Es wäre anders, wenn nur die Daten gespeichert und der Verschlüsselungsschlüssel beispielsweise von einem Kennwort abgeleitet würde, das von einem Benutzer eingegeben werden musste.
MarioVilas