hawkmaster: PhpMyAdmin ändert Passwort ab, Problem mit Zeichensatz?

Hallo zusammen,
Ich habe folgendes Problem mit PhpMyAdmin:

Ich habe eine PHP Seite mit einem User Login Bereich.
Der User gibt seinen Namen und Passwort ein und wird dann auf die Hauptseite geleitet.
Das Passwort ist als Spalte "pwd" mit Varchar(250) in der MySQL Tabelle "userdata" gespeichert. Als Kollation habe ich "latin1_german1_ci" verwendet.
Wenn der User sich zum ersten mal registriert wird das Passwort mit
"AES_ENCRYPT('$password',@pwd_key) in der Spalte "pwd" gespeichert.

Es können also auch Sonderzeichen und nicht darstellbare Zeichen drin stehen.
Etwa: TB.·þ2d]bæø  (in Echt sind hier noch Ascii Zeichen die ich hier nicht darstellen kann!)

Das Problem tritt dann auf, wenn man mit PhpMyAdmin die MySQL Tabelle "userdata" öffnet. Also z.b. auf "Browse" ("Anzeigen") klickt und dann auf "edit" klickt. Obwohl ich nichts an den Daten ändere, wird das Passwort in einem anderen "Format" abgelegt.
PhpMyAdmin zeigt dann auch folgenden Update Befehl an:
UPDATE testdb.userdata SET pwd = 'TB.·þ2d]bæø' WHERE userdata.UserID =3 LIMIT 1 ;
Macht man da Gleiche ein zweites mal, wird kein Update gemacht.
Dann kann sich der User anschließend nicht mehr einloggen.

Ich vermute das es am Zeichensatz bzw. der Kollation liegt.
In PhpMyAdmin wird mir folgendes angezeigt:
MySQL charset: UTF-8 Unicode (utf8)
MySQL connection collation: utf8_unicode_ci

Kann der Browser event. die Sonderzeichen nicht richtig interpretieren und PhpMyAdmin meint es gab eine Änderung?

Was kann man tun?

vielen Dank
Gruss
hawk

  1. Moin!

    Ich habe eine PHP Seite mit einem User Login Bereich.
    Der User gibt seinen Namen und Passwort ein und wird dann auf die Hauptseite geleitet.
    Das Passwort ist als Spalte "pwd" mit Varchar(250) in der MySQL Tabelle "userdata" gespeichert. Als Kollation habe ich "latin1_german1_ci" verwendet.
    Wenn der User sich zum ersten mal registriert wird das Passwort mit
    "AES_ENCRYPT('$password',@pwd_key) in der Spalte "pwd" gespeichert.

    AES_ENCRYPT liefert dir einen Binärwert, keinen String im Datenbanksinn. Also ist es falsch, diesen Wert in einer VARCHAR-Spalte abzuspeichern und dafür etwas anderes als eine Binärcollation zu benutzen, weil Werte auftreten können, die keinem codierbaren Zeichen entsprechen.

    Aber abgesehen davon: Warum AES_ENCRYPT? Damit lassen sich die Passwörter alle wiederherstellen. Das ist genauso schlecht, als wären sie direkt im Klartext gespeichert. Nutze MD5() oder SHA1(), nur damit ist der String nicht wiederherstellbar - und du erhälst außerdem eine deutlich ungefährlichere und immer gleichlange Zeichenkette, die auch in VARCHAR-Spalten gespeichert werden darf.

    Und außerdem: Hast du das Passwort auch vernünftig escaped? mysql_real_escape_string() benutzt?

    Es können also auch Sonderzeichen und nicht darstellbare Zeichen drin stehen.
    Etwa: TB.·þ2d]bæø  (in Echt sind hier noch Ascii Zeichen die ich hier nicht darstellen kann!)

    Daran, dass das Forum meckert, siehst du, dass du es mit Binärwerten zu tun hast, die nicht mit normaler Stringverarbeitung benutzt werden können.

    Das Problem tritt dann auf, wenn man mit PhpMyAdmin die MySQL Tabelle "userdata" öffnet. Also z.b. auf "Browse" ("Anzeigen") klickt und dann auf "edit" klickt. Obwohl ich nichts an den Daten ändere, wird das Passwort in einem anderen "Format" abgelegt.

    Nein, PHPMyAdmin tut sein Bestes, aber da du die Datenbank falsch konfiguriert hast, gehen dir eben Zeichen verloren.

    PhpMyAdmin zeigt dann auch folgenden Update Befehl an:
    UPDATE testdb.userdata SET pwd = 'TB.·þ2d]bæø' WHERE userdata.UserID =3 LIMIT 1 ;
    Macht man da Gleiche ein zweites mal, wird kein Update gemacht.

    Beim zweiten Mal sind eben alle "bösen" Zeichen rausgefiltert.

    Dann kann sich der User anschließend nicht mehr einloggen.

    Schon nach dem ersten Update nicht mehr. :)

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Hallo Sven,
      vielen Dank für deine sachliche und hilfreiche Erklärung.
      (Ich schätze deine Comments immer sehr)
      Du hast natürlich vollkommen recht wegen der Passwort Kodierung.
      Ich hatte zuerst md5 aber aus folgendem Grund auf AES_ENCRYPT umgestellt.
      Es handelt sich um eine ganz spezielle kleine Intranet Anwendung nur für ein paar wenige User. Nicht fürs Internet.
      Neben dem normalen manuellen Login gibt es auch eine Art "Auto-Login" an einem LDAP Server.
      Ich mache dies in der Art:
      -----------------------------------------------------------------
      $pass1 = rawurldecode($PWD);
      $result = mysql_query("SELECT pwd, AES_DECRYPT(pwd,@pswd_key) as ergebnis  FROM userdata WHERE usr='".addslashes($USER)."' && pwd='".addslashes($pass1)."'") or mysql_error();
      $row = mysql_fetch_array($result);
      $bd = @ldap_bind($ad, utf8_encode($USER).$at_dn , utf8_encode($row[ergebnis])) ;
      if($bd == false){
      $ldaperror = ldap_errno($ad);
      if($ldaperror == "81"){
      ...
      ----------------------------------------------------------------------
      Ich brauche also "AES_DECRYPT" um das "echte" Passwort unverschlüsselt mit dem LDAP Server zu vergleichen.
      Mit MD5 geht das ja so nicht.
      ich weiss es ist nicht die eleganteste Art.
      Ich habe keine andere Idee wie man es sonst machen könnte.

      Auch wegen der Verifizierung des User Passworts hast du recht.
      Ich möchte alles auf "mysql_real_escape_string()" umstellen. Bisher arbeitete ich noch mit "Magic Quotes" (nicht schlagen :-) )

      Du meinst also das Problem liegt an der falschen Spalten Definition des Spalte "pwd"?

      viele Grüße und nochmals danke
      hawk

  2. echo $begrüßung;

    Ich habe folgendes Problem mit PhpMyAdmin:

    Glaub ich nicht, dass der phpMyAdmin das Problem ist. Vielmehr wird die Lücke in der Verarbeitungskette Browser<->PHP<->MySQL liegen.

    Das Passwort ist als Spalte "pwd" mit Varchar(250) in der MySQL Tabelle "userdata" gespeichert. Als Kollation habe ich "latin1_german1_ci" verwendet.
    "AES_ENCRYPT('$password',@pwd_key) in der Spalte "pwd" gespeichert.

    Du möchtest also einen verschlüsselten Wert ablegen. Betrachte diesen Wert genauso wie beispielweise Daten einer Bilddatei als Binärdaten. Daraus ergibt sich, dass ein Binärdaten-Feldtyp besser geeignet ist als ein Feld für Zeichen, dessen Zeichen je nach Kodierung unterschiedliche Bytewerte ergeben können.

    Ich vermute das es am Zeichensatz bzw. der Kollation liegt.

    Du kommunizierst mit dem MySQL-Server vermutlich auf gut Glück. Besser ist es, nach dem Verbindungsaufbau die zu verwendende Kodierung explizit zu setzen. Das geht ab PHP 5.2.3 mit mysql_set_charset() ansonsten mit einer "SET NAMES ..."-Query.

    In PhpMyAdmin wird mir folgendes angezeigt:
    MySQL charset: UTF-8 Unicode (utf8)
    MySQL connection collation: utf8_unicode_ci

    Das ist für deine Scripte uninteressant, das ist nur die Kodierung, mit der der phpMyAdmin mit dem MySQL-Server redet.

    Kann der Browser event. die Sonderzeichen nicht richtig interpretieren und PhpMyAdmin meint es gab eine Änderung?

    Auch mit dem Browser solltest du nicht "Blindflug" reden sondern ebenfalls die Kodierung angeben, in der du ihm die Dokumente auslieferst. Er wird dann Formulardaten ebenfalls in dieser Kodierung zurückliefern.

    echo "$verabschiedung $name";

    1. Hallo dedlfix,
      auch dir herzlichen Dank für deine Hilfe,
      momentan habe ich ja noch garkein Problem mit meinen Skripten bzw. Anwendung.
      Es geht mir nur um PhpMyAdmin und um zu verstehen was da mit dem Passwort passiert.

      Die Anwendung an und für sich so wie sie momentan ist, läuft ohne Probleme.
      Ein User kann sich registrieren, das Passwort wird verschlüsselt abgelegt.
      Beim nächsten Login wird das Passwort gecheckt und gegebenfall der Einlass gewährt.
      Das Problem tritt erst auf, wenn man als Admin manuell etwas in der Tabelle "userdata" mit PhpMyAdmin ändert.

      <<Auch mit dem Browser solltest du nicht "Blindflug" reden sondern ebenfalls die Kodierung angeben..>>
      Wie gesagt: momentan geht es rein um PhpMyAdmin und da kann ich dem Browser ja nichts mitgeben oder?

      Aber vielleicht ist der Ansatz zwecks Binärdaten ja ganz gut.

      viele Grüße
      hawk

      1. echo $begrüßung;

        <<Auch mit dem Browser solltest du nicht "Blindflug" reden sondern ebenfalls die Kodierung angeben..>>
        Wie gesagt: momentan geht es rein um PhpMyAdmin und da kann ich dem Browser ja nichts mitgeben oder?

        Der phpMyAdmin redet ja selbst mit dem Browser einerseits und dem MySQL-Server andererseits. Der ist also dafür verantwortlich, dass beide Richtungen über die zu verwendende Zeichenkodierung informiert werden. Bisher sind mir da keine Klagen bekannt geworden, bei denen der PMA die Ursache gewesen wäre. Allerdings kann er auch nicht zaubern. Wenn sich bestimmte Bytewerte per se nicht als Zeichen darstellen lassen, kann er daran auch nichts verbessern. Es sei denn, er weiß aufgrund des Feldtyps, das Binärdaten zu erwarten sind, dann kann er gegebenenfalls entsprechende Vorsichtsmaßnahmen treffen.

        echo "$verabschiedung $name";