Obelix: Magic Quotes

Tach,

ich habe jetzt zum Thema Magic Quotes diesen Artiekl gefunden: http://aktuell.de.selfhtml.org/artikel/phpasp/php-forum/index.htm#magic_quotes_fix_php

Allerdings gibts dazu überhaupt keine Beschreibung, weil der Autor sagt es gibt vielleicht später noch ein extra Thema dazu. Gibts aber nicht.
Jetzt suche ich entweder ein ähnlich gutes Beispiel mit guten Erklärungen, oder jemanden, der mir dieses Beispiel gut erklären könnte.

Danke, Obelix

  1. Hallo Obelix,

    das ist einfach relativ schnell erklärt, was dort passieren soll. Das Script hat meine Meinung noch einen Denkfehler.

    Magic-Quotes_GPC steht für MQ GET, POST, COOKIE

    Das bedeutet, dass alle Daten, die über $_GET, $_POST oder $_COOKIE dem Script zur Verfügung gestellt werden, mit dem Backslash maskiert werden. Die behandelten Zeichen sind der einfache und der doppelte Anführungsstrich (' und "), der Rückstrich () selbst sowie NUL (das Null-Byte).

    Henryk stellt als erste mit Hilfe der Funktion

    get_magic_quotes_gpc() fest, ob die entsprechende INI-Variable gestzt ist. Die Spezialfunktion gibt immer Antwort, egal, ob der User auf die INI-Datei zugriff hat oder nicht (-> ini_get("magic_quotes_gpc") würde dann das gleiche Ergebnis liefern).

    Wenn MQ_GPC nicht eingeschaltet ist, dann sollte er den sonst automatisch durchgeführten Vorgang "zu Fuß" nachholen für jedes der drei Arrays. Und das genau tut er nicht. Er unterscheidet noch nach der Übertragungsmethode. Dabei hat er aber übersehen, dass PHP auch bei der Übertragungsmethode POST in $_GET[] Werte zur Verfügung stellen kann. Die Verzweigung (if ..) sollte man also wieder rausbauen.

    Die Foreach()-Funktion ist etwas unvollständig programmiert, deshalb muss man for der Anwendung immer erst Fragen, ob das Argument tatsächlich ein Array ist. Da aber jedes Array auch wieder Unterarrays enthalten kann, wird rekursiv gearbeitet.

    Na, und mehr passiert hier eigentlich nicht.

    Wenn Du nun mit mysql_escape_string() arbeiten willst, musst Du die Logik genau umdrehen. Du musst dann nach der Datenübernahme fragen, ob MQ_GPC eingeschaltet war. Wenn JA, dann musst Du das Verfahren von Henryk mit der Funktion stripslashes() anwenden, um die Maskierungen wieder zu entfernen.

    Dann solltest Du alle Verarbeitungen mit den Daten durchführen und am Ende alle Daten, bevor sie an die DB übergeben werden, mit mysql_escape_string() behandeln.

    Das geht dann auch seriell (also nicht rekursiv), da ja an die DB nur Skalare (keine Arrays) übergeben werden dürfen. Also reicht ein einfaches foreach() für alle Werte deines SpeicherBuffers.

    I hoaff, Du hoast mi nun :-))

    Liebe Grüße

    Tom

    1. Sagen wir mal ich habs so halb verstanden :)
      Das Ende ist mir etwas zu hoch.

      Was ich allerdings überhaupt nicht verstehe: am Ende des Skripts wird set_magic_quotes_runtime(1); ausgeführt. Damit werden die magic quotes doch wieder aktiviert, wozu brauche ich also so ein Skript?

      1. Sagen wir mal ich habs so halb verstanden :)
        Das Ende ist mir etwas zu hoch.

        Was ich allerdings überhaupt nicht verstehe: am Ende des Skripts wird set_magic_quotes_runtime(1); ausgeführt. Damit werden die magic quotes doch wieder aktiviert, wozu brauche ich also so ein Skript?

        Hi Obelix,

        das geht nun wirklich fast nur noch mit Bildchen.

        Stell Dir einfach vor, du solltest den String

        Er sagte:"ich versteh das nicht".

        in die Datenbank speichern.

        Dann musst Du doch $gesagt mit

        $gesagt="Er sagte:"ich versteh das nicht"."

        an die Datenbank übergeben.

        in der Datenbank steht nun im Feld GESAGT

        45 72 20 73 61 67 74 65 3A 22 69 63 68 20  ....
           E  R     s  a  g  t  e  :  "  i  c  h      v  e  r

        Das bedeutet, dass der Backslash vor dem Häkchen gar nicht mit in die DB übernommen wird. Wieso denn auch? In der DB stehen die Zeichen als ASCII-Code (oder welcher für die DB zuständig ist) codiert eingetragen. Die "Demaskierung" findet allerdings noch in der API zur Datenbank statt. Übergibt man die Werte mit einem Systemaufruf (Interrupt), dürfen im Datenpuffer keine Maskierungen mehr stehen.

        Nur die Programmiersprache C (und damit auch Perl und PHP und...) mischen Zeichenstrom und Anweisungen. Pascal z.B. kennt nur eine einzige Anweisung bei Strings -> "  Das Häkchen. Wenn man also ein Häkchen schreiben will, muss man "" zwei direkt hintereinander schreiben.

        Wenn Du jetzt die Daten aus der DB wieder rausholst und Magic_Quotes_Runtime ist eingeschaltet, dann werden nach dem SELECT die Maskierungen wieder gesetzt.

        Da Du die Maskierungen aber selber vornehmen wirst, solltest Du dieses Feature auch ausschalten.

        In Deinen Strings stehen dann nur reine Werte.

        Die MQ_RT Sache schaue ich mir aber selber nochnmal genauer an. Leider sieht man ja nicht, an welcher Stelle welche Verbiegungen stattfinden.

        Grüße

        Tom

        1. Wenn du eine gute Seite zu dem Thema findest schreibs hier ein bitte :)

  2. Moin!

    Allerdings gibts dazu überhaupt keine Beschreibung, weil der Autor sagt es gibt vielleicht später noch ein extra Thema dazu. Gibts aber nicht.
    Jetzt suche ich entweder ein ähnlich gutes Beispiel mit guten Erklärungen, oder jemanden, der mir dieses Beispiel gut erklären könnte.

    Ich kann dir allgemein zu Magic-Quotes was sagen.

    In PHP kann man einstellen, ob die Daten, die man aus GET-Parametern, POST-Formularen oder Cookies erhält, automatisch ("magisch") escaped werden sollen, oder nicht.

    Der Hintergrund ist, dass viele DAUs sonst Skripte programmieren würden, mit denen sie dicke Hintertüren zum DB-Verschrotten oder sonstigen Krams hinkriegen würden. Deshalb wurde diese Option wohl mal eingeführt und standardmäßig eingeschaltet.

    magic-quotes führt für alle übergebenen Daten die Funktion addslashes() aus, noch bevor das Skript überhaupt startet. Deshalb kann man diese Option auch nachträglich im Skript nicht mehr wirkungsvoll abschalten. Der "Schaden" bzw. die Veränderung der Daten ist bereits geschehen.

    Warum sollte man magic-quotes nicht mögen? Weil man vielleicht gar nicht in Datenbanken schreiben will, sondern in Textdateien. Und da stören diese automatischen Quotes erheblich. Außerdem gibts zum escapen von Strings für den Datenbankgebrauch eigene Escape-Funktionen, die direkt aus der API der Datenbank kommen und wesentlich sicherer Zeichen escapen können. Kann ja sein, dass sich der benutzbare Zeichenvorrat der DB mal verändert. Diese Änderungen werden dann auch in der API vorgenommen und kommen so automatisch auch im Skript zu Wirkung. MySQL beispielsweise bietet (auch in PHP) die Funktion mysql_escape_string() an, die sowas macht.

    Mit anderen Worten: Warum nun im Artikel ausgerechnet magic_quotes_gpc eingeschaltet sein soll und ansonsten künstlich erzeugt wird, mag ich nicht nachvollziehen. Ich habe es lieber so, dass magic_quotes_gpc ausgeschaltet sind, und übernehme eventuell notwendiges escapen manuell.

    - Sven Rautenberg

    --
    "Beim Stuff für's Web gibts kein Material, was sonst das Zeugs ist, aus dem die Sachen sind."
    (fastix®, 13. Oktober 2003, 02:26 Uhr -> </archiv/2003/10/60137/#m338340>)
    1. Also sollte ich einfach überprüfen ob magic quotes aktiviert sind, falls ja diese deaktivieren und dann das escapen selbst vornehmen?

      Diese Lösung wäre auch mir selbst am liebsten, da ich dann weiß was passiert und nicht durcheinander komme. Das bereitet mir nämlich noch die größten Schwierigkeiten, dass die magic quotes auf manchen Systemen aktiviert und auf manchen deaktiviert sind. Würde ich das Skript nur für meinen eigenen Server schreiben wäre das kein so großes Problem.

      1. Moin!

        Also sollte ich einfach überprüfen ob magic quotes aktiviert sind, falls ja diese deaktivieren und dann das escapen selbst vornehmen?

        Im Prinzip: Ja.

        Das Problem ist: Die Einstellung muß entweder in der zentralen php.ini-Datei vorgenommen werden, oder in einer lokalen .htaccess-Datei (das wiederum muß aber erlaubt sein, dass man es machen darf).

        Mit anderen Worten: Die Kurzfassung für deine Skripte dürfte lauten
        if (magic_quotes_gpc())
        {
          die ("Bitte magic_quotes_gpc abschalten");
        }

        Dann rennt dein Skript zumindest nicht blind in sein Verderben. :)

        Die Alternative dazu ist eben, alle GET, POST und COOKIE-Angaben mit stripslashes() zu bearbeiten - und das rekursiv, weil ja auch Arrays in den Arrays stehen können.

        Ich meine, bei php.net steht bei der Funktion stripslashes() oder addslashes() in den Benutzerkommentaren sowas schon vorgefertigt drin. Ansonsten hast du ja aber auch die angegebene Funktion in SelfAktuell, die im Prinzip nichts anderes macht.

        Diese Lösung wäre auch mir selbst am liebsten, da ich dann weiß was passiert und nicht durcheinander komme. Das bereitet mir nämlich noch die größten Schwierigkeiten, dass die magic quotes auf manchen Systemen aktiviert und auf manchen deaktiviert sind. Würde ich das Skript nur für meinen eigenen Server schreiben wäre das kein so großes Problem.

        Bei PHP gibt es zwei große Probleme: magic_quotes_gpc ist eines davon, das andere heißt register_globals.

        magic_quotes_gpc erfordert entweder einen definierten Wert (sinnvollerweise off), oder Extracode zum Rückgängigmachen.

        register_globals ist noch eine Stufe schrecklicher: Damit werden dir mit Pech fremde Variablen ins Skript generiert (wenn es eingeschaltet ist). Wenn du deine Variablen also nicht alle initialisierst, hast du ein Problem.

        Deshalb: Zur Entwicklungszeit immer auch die Notices anzeigen lassen: error_reporting(E_ALL) am Skriptanfang, oder bei deiner lokalen php.ini setzen.

        Diese Einstellung kannst du dann beim auszuliefernden Skript zurückdrehen (wenn dich die Notices stören), oder eben das Auftreten von Notices programmtechnisch verhindern (keine schlechte Idee).

        - Sven Rautenberg

        --
        "Beim Stuff für's Web gibts kein Material, was sonst das Zeugs ist, aus dem die Sachen sind."
        (fastix®, 13. Oktober 2003, 02:26 Uhr -> </archiv/2003/10/60137/#m338340>)
        1. Da ich keinen Zugriff auf die php.ini habe, und das auch bei anderen nicht voraussetzen kann, muss ich eben ein workaround basteln.
          Ich habe mir das jetzt so vorgestellt, dass wenn !magic_quotes_gpc() ich eben einfach mein eigenes escape Skript aufrufe.
          Das erscheint mir als beste Lösung.

  3. Hey,

    Wie du jetzt sicher schon erfahren hast, sind diese sog. und überaus tollen
    'magic_quotes' ein Überbleibsel aus alten PHP-Versionen , die ursprünglich
    mal allen DoofNussis das Programmieren erleichtern sollten.

    Das Verhalten (magic_quotes AN oder AUS) läßt sich aber auch einfach
    umstellen, so man die Apache-Version von PHP verwendet (Normallfall).
    In einer Datei mit dem Namen ".htaccess" kannst du einfach folgendes
    eintragen, um die dollen ZauberQuotes ein- oder auszuschalten:

    #-- an (böse):
    php_flag magic_quotes_gpc on

    #-- aus (gut):
    php_flag magic_quotes_gpc off
    php_flag magic_quotes_runtime off

    Das ist der sauberste workaround, wenn man keinen Zugriff auf die "php.ini"
    hat. Und wie gesagt, wer Ahnung hat verläßt sich nicht auf die ZauberQuotes,
    sondern benutzt addslashes() oder mysql_escape_string().

    MsF,
    milky

    1. Hi Milky»»

      hat. Und wie gesagt, wer Ahnung hat verläßt sich nicht auf die ZauberQuotes,
      sondern benutzt addslashes() oder mysql_escape_string().

      Schön gesagt. Ahnung hat Obelix ja jetzt, aber noch kein fundiert abgesichertes Wissen. Wenn er nix geahnt hätte, hätte er gar nicht erst gefragt :-)

      Es herrscht hier im Forum meiner Meinung nach die Unsitte, ernsthafte basisorentierte Fragen nicht bis ins letzte Bit zu erklären, sondern einfach abzuwiegeln und mit einer Oberflächlichkeit beiseite zu wischen.

      Das geht jetzt nicht gegen Dich, sondern ich wollte es mal offen aussprechen. Einer, der sich schon mal auf eine fundierte Grundlagendiskussion einlässt ist z.B. Sven rautenberg. Mein Dank sei mit ihm. Einige andere habe ich auch noch kennengelernt aber die Mehrheit ist oft agressiv und ignorant. Das finde ich schade.

      Noch ein paar Worte zu den Unterschieden zwischen addslashes() und mysql_escape_string():

      AddSlashes() maskiert nur   ' " \ NULL
      mysql_escape_string() maskiert auch die "WhiteSpaces" (mit Ausnahme des echten Leerzeichens)  \n \r \t \b   und so weiter.
      Das ist besonders dann wichtig, wenn man den Inhalt von Textareas in der Datenbank abspeichern will.

      Ich suche dazu aber nochmal die vollständige Information raus, wenn niemand anders sie zwischenzeitlich hier verlinken sollte.

      Und es besteht zu guter Letzt ja noch die Frage, was man mit magic_quotes_runtime machen sollte. Was ist der Default, und worauf sollte man es einstellen, und vor allem warum?

      Also bitteschön! Fundierte Antworten werden gesucht.

      Grüße

      Tom