Magda: FormularWert in mysql Datenbank schreiben

Aus einem Formular kommt ein String Wert, diesen möchte ich in meine mysql Datenbank schreiben.
Doch ich glaube ich sollte ihn vorher absichern. Ich habe mir überlegt, das ich es so machen könnte um alle Probleme irgendwie abzufangen:

  
function InDatenbankSchreiben($string)  
	{  
	return mysql_real_escape_string(htmlentities($string))."' COLLATE latin1_general_cs";  
	}  

Wäre das (einigermassen) OK

Magda

  1. Hi,

    Wäre das (einigermassen) OK

    Nein. Lesen. (Auch die Folgeseite.)

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Aber da wird doch genau das: mysql_real_escape_string empfohlen!!!

      Magda

      Hi,

      Wäre das (einigermassen) OK

      Nein. Lesen. (Auch die Folgeseite.)

      MfG ChrisB

      1. Om nah hoo pez nyeetz, Magda!

        Vollzitate sind hier weder erwünscht noch notwendig.

        Nein. Lesen. (Auch die Folgeseite.)

        In 7 Minuten lassen sich diese beiden Artikel nicht aufmerksam lesen.

        Matthias

        --
        1/z ist kein Blatt Papier.

  2. Hallo,

    Aus einem Formular kommt ein String Wert, diesen möchte ich in meine mysql Datenbank schreiben.
    Doch ich glaube ich sollte ihn vorher absichern.

    jein, "absichern" ist eine schlechte Formulierung. Richtig ist allerdings: Du solltest den String auf jeden Fall so behandeln, dass er für SQL unverfänglich ist und kein Durcheinander verursachen kann.

    function InDatenbankSchreiben($string)

    {
    return mysql_real_escape_string(htmlentities($string))."' COLLATE latin1_general_cs";
    }

      
    Das ist aus zwei Gründen Unfug.  
      
    Erstens ist die Funktion htmlentities nicht für den Kontext "SQL" geeignet, sondern sollte -wenn überhaupt- erst angewendet werden, wenn du den String wieder aus der Datenbank holst und als HTML ausgeben möchtest. Und selbst dann wäre htmlentities() nicht unbedingt sinnvoll, sondern eher htmlspecialchars().  
    Für die Übergabe eines Strings über die SQL-Schnittstelle ist mysql\_real\_escape\_string() völlig angemessen, und man braucht keine weiteren Schritte zusätzlich.  
      
    Zweitens schreibt diese Funktion nichts in die Datenbank, sondern bearbeitet nur den String und liefert ihn modifiziert zurück. Daher ist der Funktionsname völlig irreführend gewählt. Das Anhängsel "' COLLATE ..." ist an dieser Stelle ebenfalls Murks - nicht zuletzt deshalb, weil es mit einem Anführungszeichen beginnt, dessen Partner weit und breit nicht zu sehen ist.  
      
    So long,  
     Martin  
    
    -- 
    Chef zum Bewerber: Es gibt zwei Dinge, auf die ich allergrößten Wert lege. Das eine ist Sauberkeit! Haben Sie übrigens die Schuhe auf der Matte abgetreten? - Ja, selbstverständlich. - Gut. Das andere ist uneingeschränkte Ehrlichkeit. Übrigens, draußen liegt gar keine Fußmatte.  
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    
    1. Das heisst also

      function InDatenbankSchreiben($string)
            {
            return mysql_real_escape_string($string);
            }

      ist ok.

      Anschliessend kann ich bei der Ausgabe mit

      htmlentities($string)

      bzw.

      htmlspecialchars($string)

      weiterarbeiten?

      Danke

      1. Hi,

        function InDatenbankSchreiben($string)
              {
              return mysql_real_escape_string($string);
              }

        ist ok.

        technisch ja, aber es ist nicht sinnvoll: Eine Funktion X aufrufen, die nichts weiter tut als ihrerseits Funktion Y aufzurufen? Da kann ich auch direkt Y aufrufen (hier: mysql_real_escape_string()), das ist einfacher und übersichtlicher.
        Abgesehen davon, dass dein gewählter Funktionsname immer noch irreführend ist.

        Anschliessend kann ich bei der Ausgabe mit

        htmlspecialchars($string)

        weiterarbeiten?

        Genau. Und zwar da, wo du den String als HTML an den Browser ausgibst, nicht vorher.

        Ciao,
         Martin

        --
        Rizinus hat sich angeblich als sehr gutes Mittel gegen Husten bewährt.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  3. hi,

    Wäre das (einigermassen) OK

    Eine schöne Übung aber das geht an Deinem Ziel vorbei. Es sind mehrere Dinge zu beachten:

    Zum einen bekommst Du Daten aus einer nicht vertrauenswürdigen Quelle, dem Formular. Hier wäre abzusichern, das keine SQL-Attacke eingeschleust werden kann, sondern nur die Daten. Verwende einen DB-Treiber, der mit Platzhaltern arbeitet, da werden die Eingaben der DB-Engine entsprechend automatisch so gequoted, dass nur passive Daten ankommen (PDO, mysqli).

    Das Nächste ist die Zeichenkodierung. Hierzu ist in erster Linie die Quelle zu beachten, d.h., stelle sicher, dass das Formular bereits beim Ausliefern an den Browser eine definierte und Dir bekannte Kodierung bekommt. So kannst Du davon ausgehen, dass die submitteten Daten dieselbe Kodierung haben (was aber auch nicht immer der Fall ist, wenn der Benutzer vor dem Submit eine andere Kodierung einstellt).

    Betrachten wir des Weiteren HTML Entities. Eine DB Engine kennt sowas gar nicht, der ist das völlig Wurscht. Ergo kannst Du darauf verzichten.

    Und nimm Dir mal richtig Zeit für den Artikel "Kontextwechsel"

    Hotti

    1. Tach!

      Zum einen bekommst Du Daten aus einer nicht vertrauenswürdigen Quelle, dem Formular. Hier wäre abzusichern, das keine SQL-Attacke eingeschleust werden kann, sondern nur die Daten.

      Es ist völlig unerheblich, wo Daten herkommen. Sie müssen sie immer kontextgerecht ausgegeben/eingefügt werden. Die einzig vertrauenswürdigen Daten sind Literale im Quelltext, und selbst bei denen muss man die Sonderzeichen beachten.

      Verwende einen DB-Treiber, der mit Platzhaltern arbeitet, da werden die Eingaben der DB-Engine entsprechend automatisch so gequoted, dass nur passive Daten ankommen (PDO, mysqli).

      Quoten bezeichnet das Einrahmen in Stringbegrenzungszeichen (meist Anführungszeichen). Passive Daten? Gibt es auch aktive? Was jedenfalls mit den Daten konkret passiert, ist Blackbox - nicht sichtbar. Der Treiber beziehungsweise die DBMS-API kümmert sich um die gefahrlose Übertragung. Wie sie konkret übertragen werden, ist dabei unerheblich. Ob sie dafür gequotet werden müssen oder nicht, spielt keine Rolle.
      "Mit Platzhaltern arbeiten" heißt konkret "Prepared Statements". Und es reicht nicht, dass der Treiber sie anbietet, man muss auch damit arbeiten. Abgesehen davon sollte man wirklich auf mysqli oder PDO umsteigen, weil die herkömmlichen mysql_*-Funktionen bereits in der nächsten Version von PHP (5.5) als missbilligt gelten und irgendwann ganz rausfliegen werden.

      Das Nächste ist die Zeichenkodierung. Hierzu ist in erster Linie die Quelle zu beachten,

      Nicht nur, die gesamte Verarbeitungskette ist zu beachten. Und zwar jedes beteiligte System und jede Übergabe in ein anderes System gleichermaßen. Es ist ja nicht so, dass einmal richtig kodierte Daten nicht auch durch Verarbeitungsfehler verunstaltet werden können.

      Betrachten wir des Weiteren HTML Entities. Eine DB Engine kennt sowas gar nicht, der ist das völlig Wurscht. Ergo kannst Du darauf verzichten.

      Das ist nicht nur ein "kann". Ein Empfänger braucht die für die Maskierung zusätzlichen/geänderten Zeichen, um die eigentlichen Werte aus dem Datenstrom korrekt identifizieren zu können. Wenn der Empfänger einer bestimmte Maskierungsart aber nicht unmittelbar erreicht werden soll, sondern noch in weiter Ferne ist, hat man die im Moment nicht notwendigen Zeichen mitten in den eigentlichen Daten stehen, was nicht nur unnötig Platz belegt, sondern auch die Verarbeitung in diesem System erschwert. Das Problem wird auch nicht einfacher, wenn die Daten am Ende gar einen ganz anderen Empfänger erreichen sollen.

      dedlfix.

      1. Om nah hoo pez nyeetz, dedlfix!

        Abgesehen davon sollte man wirklich auf mysqli oder PDO umsteigen, weil die herkömmlichen mysql_*-Funktionen bereits in der nächsten Version von PHP (5.5) als missbilligt gelten und irgendwann ganz rausfliegen werden.

        Das heißt, wenn der Hoster upgraded, werden viele Seiten plötzlich[*] Müll anzeigen? Gibt es eigentlich eine Seite, die die wichtigsten Dinge gegenüberstellt? Denn allein die Syntax sieht doch sehr unterschiedlich aus.

        [*] plötzlich ist relativ, missbilligte HTML-Attribute gibts ja auch noch

        Matthias

        --
        1/z ist kein Blatt Papier.

        1. Tach!

          Abgesehen davon sollte man wirklich auf mysqli oder PDO umsteigen, weil die herkömmlichen mysql_*-Funktionen bereits in der nächsten Version von PHP (5.5) als missbilligt gelten und irgendwann ganz rausfliegen werden.
          Das heißt, wenn der Hoster upgraded, werden viele Seiten plötzlich[*] Müll anzeigen?

          Versionswechsel mit Wegfall mehr oder weniger wichtiger Features gab es in der Vergangenheit auch bereits. Die Hoster werden es auf die bewehrt vorsichtige Art mit langfristiger Ankündigung und dem Weiterbetreiben alter Versionen (auch über das Supportzeitraum hinaus) irgendwie hinbekommen, dass nicht das halbe Internet kaputtgeht.

          Gibt es eigentlich eine Seite, die die wichtigsten Dinge gegenüberstellt? Denn allein die Syntax sieht doch sehr unterschiedlich aus.

          So viel anders ist sie jetzt auch nicht, zumindest nicht, wenn man mysqli prozedural verwendet: http://de3.php.net/manual/en/mysqli.quickstart.dual-interface.php Allerdings muss man nun immer die Verbindungskennung mit durchreichen. Weniger Tipparbeit wird es, wenn man auf die objektorientierte Art umsteigt.[1]

          $res = mysqli_query($mysqli, "SELECT  
          $res = $mysqli->query("SELECT  
          $res = mysql_query("SELECT
          

          Die dritte Zeile ist die herkömmliche Form, aber ohne dass eine Verbindungskennung übergeben wurde. Das funktioniert aber nicht, wenn man mehrere Verbindung braucht. Diese Variante sucht sich selbst die erstbeste offene Verbindung.

          Hier auch noch ein Vergleich zwischen mysql, mysqli und PDO: http://de3.php.net/manual/en/mysqlinfo.api.choosing.php
          Das waren jetzt nur die einfachen Umstiegsszenarien, bei denen keine neue Funtionalität verwendet wird. Der Umstieg auf Prepared Statements ist zugegebenermaßen eine ganze Ecke aufwendiger (und mit PDO wiederum etwas einfacher als bei mysqli). Im PHP-Handbuch sind Beispiele für alle Anwendungsarten zu finden.

          [1] "Ohh, OOP, kann ich nicht" - Wer sich auf diese Ausrede festlegen will, bitteschön. Es geht nur darum, Funktionen und Eigenschaften eines Objekts zu verwenden, nicht darum, das ganze Programm objektorientiert zu entwerfen oder umzuschreiben.

          dedlfix.

      2. hi,

        Zum einen bekommst Du Daten aus einer nicht vertrauenswürdigen Quelle, dem Formular. Hier wäre abzusichern, das keine SQL-Attacke eingeschleust werden kann, sondern nur die Daten.

        Es ist völlig unerheblich, wo Daten herkommen.

        Das würde ich mal nicht so dogmatisch in die Welt hinausschreien. Ein Programmierer sollte von Anfang an den Unterschied kennen zwischen vertrauensürdigen und nicht vertrauenswürdigen Daten.

        Schönen Sonntag.
        Hotti

        1. Tach!

          Es ist völlig unerheblich, wo Daten herkommen.
          Das würde ich mal nicht so dogmatisch in die Welt hinausschreien. Ein Programmierer sollte von Anfang an den Unterschied kennen zwischen vertrauensürdigen und nicht vertrauenswürdigen Daten.

          Definiere "vertrauenswürdige Daten", und dazu den Unterschied beim Einfügen in andere Kontexte!

          dedlfix.