WernerK: Doppelte Backslahes, woher?

Hallo,

in einem Formular kann ein Anwender Verzeichnis Pfade angeben.
z.b.
C:\programme\test\nocheinverzeichnis\1\

Diese werden in einer MySQL Tabelle gespeichert.
In der Datenbank stehen diese Pfade dann aber immer mit doppelten Backslashes

Woher kommt das?
Liegt das an "magic_quotes"?

vielen Dank
Werner

  1. Hallo,

    Hallo!

    Diese werden in einer MySQL Tabelle gespeichert.
    In der Datenbank stehen diese Pfade dann aber immer mit doppelten Backslashes

    Woher kommt das?
    Liegt das an "magic_quotes"?

    Ich kenne magic_quotes nicht, aber es hört sich ganz danach an, dass es daran liegt. Dieses Magic_quotes wird wohl die Backslashs sowie auch ', " und andere Zeichen mit Backslashes masklieren. Da kommen dann eben Dinge wie \ " ' u.ä raus.

    1. Hallo,

      kann man irgendwie prüfen ob Magic_quotes eingeschaltet ist oder nicht?

      Wenn nicht
      dann normal speichern

      Hmm.
      wenn es aber eingeschaltet ist, kann man dann überhaupt erreichen dass Formularwerte mit einen \ auch nur so mit einzelenem \ gespeichert werde?

      Gruss
      Werner

      1. Moin

        kann man irgendwie prüfen ob Magic_quotes eingeschaltet ist oder nicht?

        Du kannst mit der Funktion stripslashes() bei der Ausgabe die Slashes entfernen. Die Slashes werden beim Auslesen hinzugefügt und sollten eigentlich nicht in der Datenbank geschrieben sein.

        Gruß Bobby

        --
        -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
        -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
        ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
        1. Im Grunde ist es ja wichtig, dass die \ geqoutet werden, für das Erstellen des SQL-Statements. Angenommen die Eingabe würde lauten: "C:\Programme\new" dann würde es ja dazu führen, dass ein Newline im String interpretiert wird:
          "C:\Programme\new"
          \n ----------^
          und im Textfeld eingetragen würde:
          "C:\Programme
          ew"

          Kann es sein, dass dieses magic qoutes die Aufgabe übernimmt und anschließend nochmal eine andere quote Methode das Statement quoutet?

          Markus**

          1. Im Grunde ist es ja wichtig, dass die \ geqoutet werden, für das Erstellen des SQL-Statements. Angenommen die Eingabe würde lauten: "C:\Programme\new" dann würde es ja dazu führen, dass ein Newline im String interpretiert wird:
            "C:\Programme\new"
            \n ----------^

            und was, wenn der string 'C:\Programme\new' lautet? :)

          2. Moin

            Im Grunde ist es ja wichtig, dass die \ geqoutet werden, für das Erstellen des SQL-Statements. Angenommen die Eingabe würde lauten: "C:\Programme\new" dann würde es ja dazu führen, dass ein Newline im String interpretiert wird:

            Jetzt prügelt mich, wenn ich falsch liege. Es muss doch bei der Speicherung in die Datenbank nur gegen MySQL-Injection etwas getan werden. Mit mysql_real_escape_string() bzw. mysqli_real_escape_string() und dem Setzen des Wertes in einfache Hochkommas ist doch beim Speichern genug getan. Alles weitere ist doch erst bei der Ausgabe zu prüfen (um XSS zu vermeiden)

            Und magic.quotes quotet automatisch alle Ausgaben. Sodas man stripslashes() bemühen muss um die Ausgabe richtig zu gestalten. Außerdem sind Funktionen wie striptags(), htmlentities() oder auch htmlspecialchars() für die korrekte Ausgabe vorgesehen.

            Oder sehe ich das falsch?

            Gruß Bobby

            --
            -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
            -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
            ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
            1. Oder sehe ich das falsch?

              nein, siehst du richtig - die daten sollen nur zur ausgabe in einen bestimmten kontext maskiert werden und in ihrer rohform gespeichert werden

              nur weil du weisst, dass du "Question & Answer" mal in html ausgibst, speicherst du das doch nicht als "Question &amp; Answer" in die datenbank

              1. Moin

                Oder sehe ich das falsch?

                nein, siehst du richtig

                Danke, ich dacht schon ich bin blöd geworden... :-D

                Gruß Bobby

                --
                -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
                -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
                ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
          3. Hi,

            Im Grunde ist es ja wichtig, dass die \ geqoutet werden, für das Erstellen des SQL-Statements. Angenommen die Eingabe würde lauten: "C:\Programme\new" dann würde es ja dazu führen, dass ein Newline im String interpretiert wird:
            "C:\Programme\new"

            Nein, das wuerde nur passieren, wenn du das als Textliteral im geparsten PHP-Code notierst.
            Wenn der Wert aber beispielsweise aus einer Formulareingabe stammt, dann ist \n einfach nur ein , gefolgt von einem n, und nichts anderes.

            MfG ChrisB

            --
            „This is the author's opinion, not necessarily that of Starbucks.“
      2. Hallo,

        kann man irgendwie prüfen ob Magic_quotes eingeschaltet ist oder nicht?

        Ja, get_magic_quotes_gpc

        mfg. Daniel

  2. echo $begrüßung;

    Leider wurde in den bisherigen Antworten eine Menge nicht sehr sinnvolles geschrieben.

    Das EVA-Prinzip wurde nicht umsonst erfunden. Trenne den Programmablauf in die Teilschritte Eingabe, Verarbeitung und Ausgabe! Wenn Eingabedaten bearbeitet werden müssen, um sie in ihrer Rohform zu erhalten, dann macht man das geschickterweise gleich bei oder nach der Übernahme, nicht erst zur Ausgabe. Dann hat man die Rohdaten vorliegen und muss nicht bei jedem Verarbeitungsschritt berücksichtigen, dass da irgendwelche Sonderzeichen enthalten sein können, die für den derzeitigen Verarbeitungschritt gar nicht benötigt werden. Erst wenn es zur Ausgabe geht, werden die Daten dem Ausgabekontext entprechend behandelt / neu verpackt.

    in einem Formular kann ein Anwender Verzeichnis Pfade angeben.
    C:\programme\test\nocheinverzeichnis\1\ Diese werden in einer MySQL Tabelle gespeichert.
    In der Datenbank stehen diese Pfade dann aber immer mit doppelten Backslashes
    Liegt das an "magic_quotes"?

    Das ist im PHP-Umfeld die wahrscheinlichste Ursache. Derzeit noch. Ab PHP6 wird es das Feature nicht mehr geben. Magic Quotes sind dafür gedacht, ohne dass der Programmierer sich darum kümmern muss, SQL-Injection zu verhindern. Doch sie setzen an einem falschen Zeitpunkt an, nämlich bei den Eingabedaten. Wenn Daten erst noch verarbeitet werden oder überhaupt keine Speicherung in einem DBMS vorgesehen ist, sind diese Magic Quotes mindestens überflüssig.

    Im PHP-Handbuch gibt es ein Kapitel zu den Magic Quotes. Es gibt darin auch den Abschnitt Disabling Magic Quotes, der beschreibt, wie man sie loswird. Entweder durch Ändern der Konfiguration oder am Scriptanfang mit einer Funktion. Diese berücksichtigt auch, ob MQ eingeschaltet sind oder nicht. (Konfigurationseinstellungen kontrolliert man ansonsten mit einer phpinfo()-Ausgabe, auch der aktuelle Wert für magic_quotes_gpc kann dort eingesehen werden.) Wenn irgendwann PHP6 erscheint, braucht man nur noch dieses paar Codezeilen zu entfernen und fertig ist. Verteilt man hingegen stripslashes() im gesamten Script hat man wesentlich mehr Aufwand, diese Aufrufe aufzuspüren und zu eliminieren.

    Wenn man die Magic Quotes losgeworden ist, muss man nun selbstverständlich oben erwähnten Grundsatz berücksichtigen, und Ausgabedaten selbst und kontextgerecht behandeln. Da man das ja nicht nur in Richtung DBMS sondern beispielsweise auch in Richtung HTML beachten muss, sollte man ja dieses Prinzop schon kennen.

    echo "$verabschiedung $name";

    1. Hallo
      danke für deine ausführliche erklärung.

      So wie ich dem PHP Code entnehme (ich arbeite an einem vorhandenen Projekt) werden alle Daten mit PDO und Prepared Statements gearbeitet.

        
      $dbInsertConfigdirectories = $DBO->prepare("INSERT INTO directories (ConfigDirectoriesName,ConfigDirectoriesPath) VALUES (:configdirectoriesname,:configdirectoriespath) ");  
        
      $dbInsertConfigdirectories->bindParam(':configdirectoriesname', $key);  
      $dbInsertConfigdirectories->bindParam(':configdirectoriespath', $val);  
      $dbInsertConfigdirectories->execute();  
      
      

      Hier dürfte doch die Gefahr der SQL Injection gebannt sein oder?

      Wenn ich es richtig verstehe, dann kann ich nur einen Pfad mit einfachen Backslashes speichern, wenn "magic_quotes" auf OFF steht (sei es in der Php.ini oder im Script)
      Also
      C:\Programme\Test\verz\new\

      Oder wäre es besser man entfernt die doppelten Backslashes erst wieder beim auslesen?

      Gruss
      Werner

      1. echo $begrüßung;

        So wie ich dem PHP Code entnehme (ich arbeite an einem vorhandenen Projekt) werden alle Daten mit PDO und Prepared Statements gearbeitet.
        Hier dürfte doch die Gefahr der SQL Injection gebannt sein oder?

        Ja, bei Prepares Statements kann prinzipbedingt keine SQL-Injection auftreten. Zumindest nicht über die mit Platzhalter und Binding versendeten Daten. Um so wichtiger ist es, die Daten im Rohzustand vorliegen zu haben.

        Wenn ich es richtig verstehe, dann kann ich nur einen Pfad mit einfachen Backslashes speichern, wenn "magic_quotes" auf OFF steht (sei es in der Php.ini oder im Script)

        Magic Quotes (GPC) wirkt auf GET/POST/Cookie-Daten. Wenn du aus anderen Quellen Daten bekommst, sind diese nicht von den M.Q. betroffen. Wenn du auch noch Daten aus diesen anderen Quellen mit GPC-Daten gemeinsam verarbeiten willst, wird das Ganze nicht einfacher, wenn die einen so und die anderen anders aussehen. (Und nein, sie alle gleichmäßig zu verunstalten ist nicht die optimale Lösung.)

        Oder wäre es besser man entfernt die doppelten Backslashes erst wieder beim auslesen?

        Nein, das ist überhaupt keine gute Idee, denn in der Datenbank stehende doppelte Backslashes werden auch als solche angesehen. Das heißt, es sind jeweils zwei Zeichen statt einem, was beim Stringlängenermitteln und Sortieren zu falschen Ergebnissen führt und obendrein auch noch mehr Speicherplatz einnimmt, der bei der Feldlänge berücksichtigt werden muss.

        Wenn du an der Ausgabe programmierst, ist es unnötiger Aufwand, sich stets daran erinnern zu müssen und zu berücksichtigen, dass die Daten bei der Eingabe verunstaltet wurden.

        echo "$verabschiedung $name";

        1. Hallo,

          ok, verstanden danke.
          Abschliesend noch eine Frage bzw. Bitte.
          Im Php Manual habe ich zum obigen Problem folgendes gefunden:

            
          if (get_magic_quotes_gpc()) {  
              function stripslashes_deep($value)  
              {  
                  $value = is_array($value) ?  
                              array_map('stripslashes_deep', $value) :  
                              stripslashes($value);  
            
                  return $value;  
              }  
            
              $_POST = array_map('stripslashes_deep', $_POST);  
              $_GET = array_map('stripslashes_deep', $_GET);  
              $_COOKIE = array_map('stripslashes_deep', $_COOKIE);  
              $_REQUEST = array_map('stripslashes_deep', $_REQUEST);  
          }  
          
          

          Ich verstehe das nicht so ganz mit dem "array_map"
          Warum wird das so kompliziert gemacht?

          Wenn ich es so mache (in $val ist der Verzeichnispfad):

          foreach ($_POST as $key => $val){
            if (get_magic_quotes_gpc()) {
             $val = stripslashes($val);
          $dbInsertConfigdirectories->bindParam(':configdirectoriespath', $val);
              $dbInsertConfigdirectories->execute();

          }
          klappt es doch auch?

          Gruss
          Werner

          1. Hi,

            Ich verstehe das nicht so ganz mit dem "array_map"

            Die grundsaetzliche Funktionsweise dieser Funktion aber schon?

            Warum wird das so kompliziert gemacht?

            Was findest du daran kompliziert?

            Wenn ich es so mache (in $val ist der Verzeichnispfad):

            foreach ($_POST as $key => $val){
              if (get_magic_quotes_gpc()) {
               $val = stripslashes($val);

            klappt es doch auch?

            Fuer deinen Sonderfall vielleicht. Du verarbeitest die von den Backslashes befreiten Wert direkt und ausshliesslich an dieser Stelle weiter.

            Die andere Funktion veraendert aber a) die Inhalte der Original-Arrays - so das man sie anschliessend wieder ueberall im Script "normal" verwenden kann, und b) beruecksichtigt sie auch, dass die Inhalte ihrerseits wieder Arrays sein koennten.

            MfG ChrisB

            --
            „This is the author's opinion, not necessarily that of Starbucks.“
          2. echo $begrüßung;

            Wenn ich es so mache (in $val ist der Verzeichnispfad):

            foreach ($_POST as $key => $val){
              if (get_magic_quotes_gpc()) {
               $val = stripslashes($val);
            $dbInsertConfigdirectories->bindParam(':configdirectoriespath', $val);
                $dbInsertConfigdirectories->execute();
              }
            klappt es doch auch?

            Neben dam was ChrisB schrieb, ist es keine gute Idee, die Auswirkungen von M.Q. mitten im Script zu beseitigen. Vielleicht ist das nur deine einzige Stelle, an der du die POST-Daten verarbeitest, aber stell dir mal vor, du willst später das Script erweitern und weitere Post-Daten verarbeiten. Dann brauchst du schon wieder eine MQ-Entfernung. Und noch weiter gedacht steigst du irgendwann mal auf PHP6 um und hast an mehreren Stellen die M.Q.-Behandlung zu entfernen ...

            Mach dir nicht unnötig Arbeit. Füg die M.Q.-Entfernung gemäß Handbuch-Beispiel einmalig am Scriptanfang ein, dann kannst du komplett vergessen, dass es so etwas wie M.Q. gab und dich unabgelenkt deiner eigentlichen Aufgabenstellung widmen.

            echo "$verabschiedung $name";