Warum druckt PDO mein Passwort, wenn die Verbindung fehlschlägt?

Lesezeit: 6 Minuten

Benutzer-Avatar
Der Surriker

Ich habe eine einfache Website, auf der ich mit PDO eine Verbindung zu einem MySQL-Server herstelle.

$dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306',
               'USER',
               'SECRET', 
               array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

Ich hatte etwas Verkehr auf meiner Website und das Verbindungslimit des Servers wurde erreicht, und die Website wirft diesen Fehler mit my schmucklos Passwort drin!

Schwerwiegender Fehler: Nicht abgefangene Ausnahme „PDOException“ mit Meldung „SQLSTATE[08004] [1040] Zu viele Verbindungen’ in /home/domain/html/index.php:xxx Stack-Trace: #0 /home/domain/html/index.php(64): PDO->__construct(‘mysql:host=loca… ‘, ‘USER’, ‘SECRET’, Array) #1 {main} in /home/domain/html/index.php in Zeile 64 geworfen

Ironischerweise bin ich aus Sicherheitsgründen auf PDO umgestiegen, was mich wirklich schockiert hat, denn genau diesen Fehler kann man auf den meisten Seiten sehr leicht durch einfaches HTTP-Flooding provozieren.

Ich habe meine Verbindung jetzt in einen Try/Catch-Block gepackt, aber ich finde das immer noch katastrophal!

Ich bin neu bei PDO und daher lautet meine Frage: Was muss ich tun, um sicher zu sein? Wie stelle ich auf sichere Weise eine Verbindung her? Gibt es andere bekannte Sicherheitslücken wie diese, die ich beachten muss?

  • Siehe: stackoverflow.com/questions/5811834/… Für ein Loch bei der Verwendung dynamischer Tabellen-/Datenbank-/Spaltennamen und wie man dieses Loch stopft.

    – Johann

    23. Juni 2011 um 13:47 Uhr

  • Ich stimme voll und ganz dem Ausschalten von Fehlern in der Produktion, Try/Catch und solchen Dingen zu, aber überlegen Sie, ob Sie ein Offshore-“Team” von Programmierern haben, bei dem das Passwort “Junior”-Programmierern nicht bekannt sein sollte, dies ist, wie Sie sagten a „katastrophales“ Sicherheitsleck. Ganz zu schweigen von unerfahrenen Programmierern, die sich überhaupt nicht darum kümmern, Fehler auszuschalten. Vor diesem Hintergrund bin ich verblüfft über diese Entscheidung, das Passwort bei einem Fehler preiszugeben.

    – IMB

    29. Mai 2012 um 13:43 Uhr


  • Holy Moly, das ist KRANK! ACH DU LIEBER GOTT! Das ist absolut unverschämt! Sie brauchen mehr Upvotes, nur um cool zu bleiben und nicht in CAPS RAGE zu geraten.

    – Haifisch

    8. Juni 2013 um 17:40 Uhr

  • Mögliches Duplikat: Uncaught PDOException enthüllt Benutzername und Passwort

    – Peter Mortensen

    21. April 2020 um 16:46 Uhr


  • Was in keiner dieser Antworten erwähnt wird, ist, dass es eine schlechte Praxis ist, diese Informationen überhaupt in die Protokolle einfließen zu lassen (siehe Spickzettel zur OWASP-Protokollierung). Sie möchten also nicht einfach die Ausnahme abfangen, eine generische Nachricht ausgeben und die echte PDO-Nachricht protokollieren, da sich die Anmeldeinformationen dann in Ihren Protokollen befinden. Machen Sie zumindest eine str_replace um diese Informationen zu schwärzen, bevor Sie sie protokollieren.

    – Ben Y

    2. Januar um 19:07 Uhr

Du solltest haben display_errors = off in Ihrer PHP.ini, um dieses Problem zu vermeiden. Fehler, die Details wie diese offenbaren, kommen neben PDO von vielen anderen Stellen.

Ja, Sie sollten es auch in einem Try/Catch-Block haben.

Du kannst auch $pdo->setAttribute(PDO::ERRMODE_SILENT), aber dann müssen Sie die Fehlercodes manuell überprüfen, anstatt einen Try/Catch-Block zu verwenden. Sehen http://php.net/manual/en/pdo.setattribute.php für weitere Fehlerkonstanten.

  • @Joe, dann solltest du das mit den PDO-Entwicklern besprechen. Ich sehe kein Problem damit, Informationen vom Stack wie folgt zurückzugeben. Sobald Sie sich dessen bewusst sind, ist es kein Problem. Natürlich wird das Try/Catch bei manchen Anwendungen vergessen … für einige wird es zwangsläufig ein Problem sein … da haben Sie recht.

    – Brad

    23. Juni 2011 um 14:23 Uhr


  • Beide Vorschläge scheinen bei mir nicht zu funktionieren. Wenn die Verbindung fehlschlägt, wird der Fehler-Stack auf dem Bildschirm ausgegeben, wobei das Klartext-Passwort sichtbar ist. Ich verwende PHP ActiveRecord.

    – Alexandre R. Janini

    30. Juni 2015 um 20:24 Uhr

Benutzer-Avatar
Mathias

Eine einfache Problemumgehung besteht darin, die vom PDO-Konstruktor ausgelöste PDOException abzufangen:

try {
    $dbh  =  new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER',
    'SECRET', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
} catch (PDOException $e) {
    throw new Exception($e->getMessage());
}

  • …das heißt, einen Entwickler ohne eine Fehlermeldung zurückzulassen, die ihm sonst bei der Lösung eines Problems helfen würde.

    – Ihr gesunder Menschenverstand

    2. Juni 2016 um 6:00 Uhr

  • Bleibt bei der Ausnahme „Verbindung zur Datenbank konnte nicht hergestellt werden“ der Entwickler ohne Informationen? Ich glaube nicht

    – Mathias

    2. Juni 2016 um 14:03 Uhr

  • Das Grundkonzept ist schlecht. Niemand sollte ein einfaches Passwort in ein Objekt einfügen und es im Gedächtnis behalten. Die richtige Lösung wäre, den PDO-Code zu ändern und nicht das einfache Passwort in die Nachricht einer Ausnahme einzufügen. Ich halte dies für einen Fehler und eine Sicherheitslücke in PDO selbst.

    – nagylzs

    11. April 2017 um 12:00 Uhr

  • @YourCommonSense Das lässt sich leicht beheben (und ich habe in einer Bearbeitung angegeben, wie).

    Benutzer149341

    21. August 2018 um 20:53 Uhr

  • @duskwuff vielen Dank. Es löst wirklich ein Problem. Ich habe bereits alle meine Tutorials aktualisiert. Das einzige, was ich hinzufügen muss, ist, dass, wenn eine Funktion verwendet wird, um den Verbindungscode zu umschließen (wie es normalerweise der Fall ist), sie keine rohen Anmeldeinformationen als Parameter akzeptieren sollte, sondern sie als Array oder Objekt akzeptieren oder in der abrufen sollte Karosserie. Andernfalls wird das Problem eine Ebene nach oben verschoben, bleibt aber bestehen.

    – Ihr gesunder Menschenverstand

    1. April 2019 um 10:23 Uhr

Benutzer-Avatar
Robert Pitt

Ok, das hat mich ein bisschen zum Lachen gebracht. Die Verwendung der Fehlerberichterstattung dient Debugging-Zwecken und ermöglicht es Ihnen, Probleme schnell zu finden und zu beheben.

Wenn Sie sich in einer Live-Umgebung befinden, sollte Ihr Server nur für die interne Protokollierung und nicht für die direkte Ausgabe konfiguriert sein, also müssen Sie im Grunde die Ausgabe von Fehlern in Ihrem deaktivieren php.ini.

display_errors = Off

Aber während Sie sich in Ihrer Testumgebung befinden, ist dieser Stack lediglich ein Werkzeug, das Ihnen hilft, und ist konfigurierbar.

Wenn Fehler in einer Live-Umgebung auftreten, werden sie protokolliert, daher sollten Sie Ihre Protokolldateien immer überprüfen und dann entsprechend beheben.

Die Leute mögen angeben, dass Sie Fehler in Ihrer PHP-Anwendung verwalten können, aber aus persönlicher Sicht denke ich, dass dies der falsche Weg ist. Die Konfiguration der INI- und Konfigurationsdateien für Ihren Webserver und MySQL/SQL-Server führt zu einer schärferen Verwaltung.

Wenn es sich bei Ihrer Anwendung um eine öffentliche Anwendung handelt, wäre es auch eine gute Idee, Fehler innerhalb der Anwendung zu behandeln, da ein großer Prozentsatz der Clients möglicherweise gemeinsam gehostet wird und keinen vollständigen Zugriff auf Serverkonfigurationen hat.

Benutzer-Avatar
Wesley Abbenhuis

Wir verwenden verschlüsselte Benutzernamen und Passwörter und entschlüsseln diese im PDO-Konstruktor. Dann fangen wir die PDOException ab und werfen eine neue PDOException mit der Meldung der alten Ausnahme, sodass der Trace nur den verschlüsselten Benutzernamen und das Passwort anzeigt.

Eine gute Verschlüsselungsbibliothek für PHP ist entschärfen/php-verschlüsselung.

Beispielcode:

<?php
class myPDOWrapper extends PDO
    {

        public function __construct(string $dns, string $encodedUser, string $encodedPassword)
        {
            try {
                parent::__construct($dns, $this->decodeFunction($encodedUser), $this->decodeFunction($encodedPassword),
                    [
                        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    ]
                );
            }
            catch (PDOException $exception) {
                throw new PDOException($exception->getMessage());
            }
        }

        private function decodeFunction(string $encoded): string
        {
            return \Defuse\Crypto\Crypto::decrypt($encoded, $this->decodeKey());
        }

        private function decodeKey(): \Defuse\Crypto\Key
        {
            static $key = null;

            if(null === $key) {
                $key = \Defuse\Crypto\Key::loadFromAsciiSafeString(getenv('MY_PDO_DECODE_KEY'));
            }

            return $key;
        }
    }

1328680cookie-checkWarum druckt PDO mein Passwort, wenn die Verbindung fehlschlägt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy