Professor Hase: Einstiegsfragen für sicheres Verarbeiten von Formularen

Hallo SELF-Community,

da ich nun _erstmals_ anfange, mich mit der Verwendung von PHP in Kombination mit einer MYSQL Datenbank zu beschäftigen, habe ich die letzten Tage sowohl hier im Archiv, als auch via Google nach entsprechenden Informationen gesucht.

Immer wieder habe ich dabei von SQL-Injection und Cross-Site-Scripting gelesen. Die entsprechenden Gegenmaßnahmen sind für mich aber teilweise zu verwirrend erklärt.

Bevor ich mich also mit Detailfragen an Euch wende, würde ich gerne wissen, ob ich Folgendes _richtig_ verstanden habe oder ob eine der folgenden Aussagen falsch ist.

* Nachdem ich ( zB für ein Weblog ) Daten aus einem Formular übernommen habe, verwende ich, _bevor_ die Daten in die Datenbank geschrieben werden, die php-Funktion mysql_real_escape_string.

* Alles andere soll ich zunächst so lassen, wie es der User mir übermittelt hat und die Daten somit nun an die Datenbank senden.

* Wenn ich nun bei der Ausgabe der Daten ( ich bleibe beim Beispiel Weblog ) möchte, daß das Schriftbild gleich bleibt, dann muß ich ja verhindern, daß Dinge wie Überschriften oder CSS-Formatierungen nicht in die endgültige Seitenausgabe kommen. Daher verwende ich _nach_ dem Auslesen aus der Datenbank und _vor_ der Weitergabe an den Client die php-Funktion htmlspecialchars.

Ist das _soweit_ mal richtig verstanden?

Folgefragen:

  1. Womit muß ich mich beschäftigen, wenn ich zwar vermeiden will, daß jemand mit <h1> oder <span style="color:red"> das Textlayout verunstaltet ... aber trotzdem dem nicht im Weg stehen will, der zB den Satz "Überschriften werden in html mit <h1> ausgezeichnet." schreibt?

  2. Gelegentlich habe ich auch gelesen, daß die Funktionen addslashes() und stripslashes() unverzichtbar sind für eine sichere Verarbeitung. Stimmt das?

  3. Womit muß ich mich beschäftigen, wenn ich Sätze wie "Geben Sie dem User nur die Rechte für die Datenbank, die unbediungt nötig sind" lese?

Ich danke schon im Voraus für die Beantwortung meiner ersten Datenbankverarbeitungsfragen.

mfG

Professor Hase

EPILOG: ( kein LeseMUSS *g* )

Als ich begonnen habe, mich mit html und CSS zu beschäftigen, mußte ich zwar auch öfters etwas nachlesen, im Grunde habe ich aber immer recht schnell verstanden, worum es geht, was die DO´S und DONT`S sind. Auch die ersten Gehversuche mit php selbst waren kein all zu großes Problem. Aber was die sichere Formularverarbeitung für eine Datenbank betrifft, sieht es leider anders aus. Je mehr Informationen ich diesbezüglich suche, egal ob hier oder woanders, umso verwirrter bin ich und umso mehr habe ich das Gefühl, _nichts_ zu verstehen.

Ich hätte mir gewünscht, eine Seite zu finden, auf der man wirklich _Schritt für Schritt_ lernen kann, wie man gefährliche Angriffe auf eine Datenbank verhindern kann. Leider ist es aber so, daß auf jeder Seite, die ich zu dem Thema lese, wieder mehrere Dinge stehen, die ich nicht verstehe. Wenn ich diesen Sachen dann nachgehe, kommen die nächsten Unbekannten usw.

Mich würde interessieren, ob es anderen bei ihren ersten diesbezüglichen Gehversuchen auch so ergangen ist und wie die sich weitergeholfen haben. Ich werde jedenfalls versuchen, mit Hilfe des Forums so weit zu kommen, daß ich im Endeffekt einen _wirklich sicheren_ und dabei so schlank und einfach wie möglichen php-Code habe. Ich werde versuchen, immer, wenn ich einen Schritt weiter bin und das Gefühl habe, etwas verstanden zu haben, dies in einer Beispielseite online zu stellen und hier samt php-Quellcode zu posten. Für die vielen Fragen und Dummheiten meinerseites, die dabei sicher entstehen werden, bitte ich schon jetzt um Entschuldigung und Nachsicht. :-)

  1. hi,

    * Nachdem ich ( zB für ein Weblog ) Daten aus einem Formular übernommen habe, verwende ich, _bevor_ die Daten in die Datenbank geschrieben werden, die php-Funktion mysql_real_escape_string.

    Ja.

    * Alles andere soll ich zunächst so lassen, wie es der User mir übermittelt hat und die Daten somit nun an die Datenbank senden.

    Ja.

    * Wenn ich nun bei der Ausgabe der Daten ( ich bleibe beim Beispiel Weblog ) möchte, daß das Schriftbild gleich bleibt, dann muß ich ja verhindern, daß Dinge wie Überschriften oder CSS-Formatierungen nicht in die endgültige Seitenausgabe kommen.

    Das "Schriftbild" ist deine geringste Sorge. Wenn ich aber bspw. Javascript-Code einbringen kann, der den Nutzern Cookies stielht o.ä. ...

    Daher verwende ich _nach_ dem Auslesen aus der Datenbank und _vor_ der Weitergabe an den Client die php-Funktion htmlspecialchars.

    Ja.

    Ist das _soweit_ mal richtig verstanden?

    Ja.

    (Viele "Ja"s bis jetzt ... die natürlich hier kein LMAA bedeuten ;-))

    1. Womit muß ich mich beschäftigen, wenn ich zwar vermeiden will, daß jemand mit <h1> oder <span style="color:red"> das Textlayout verunstaltet ... aber trotzdem dem nicht im Weg stehen will, der zB den Satz "Überschriften werden in html mit <h1> ausgezeichnet." schreibt?

    Lass ihn einfach

    Überschriften werden in html mit <h1> ausgezeichnet.

    eingeben - und gut.

    htmlspecialchars macht daraus

    Überschriften werden in html mit &lt;h1&gt; ausgezeichnet.

    • und das zeigt dein Browser dann als "... mit <h1> ausgezeichnet" _an_.
    1. Gelegentlich habe ich auch gelesen, daß die Funktionen addslashes() und stripslashes() unverzichtbar sind für eine sichere Verarbeitung. Stimmt das?

    Nein.

    stripslashes kann ggf. erforderlich werden, wenn die nutzlose Einstellung magic_quotes_gpc aktiviert ist - die stellt den Sonderzeichen ", ', \ und NUL automatisch einen maskierenden Backslash voran in _allen_ Daten, die dein Script per GET/POST/COOKIE bereitgestellt bekommt.
    _Wenn_ diese Funktion die Daten bereits "versaut" hat - abzuprüfen mit get_magic_quotes_gpc() - _dann_ ist stripslashes sinnvoll, um erst mal wieder "normal" damit arbeiten zu können.
    magic_quotes_gpc ist eine Einstellung, die in aktiviertem Zustand allzu große Noobs, die sich nicht mal ansatzweise die Gedanken bzgl. Sicherheit machen, die du dir schon gemacht hast, vor sich selbst schützen soll. In PHP 6 wird sie entfallen.

    addslashes nutzen manche Leute, die mysql_real_escape_string nicht kennen, als Ersatz für dieses - ist natürlich blödsinnig. Sie macht _zufällig_ in etwa das gleiche. Aber wenn sich bspw. die MySQL-Schnittstelle zukünftig mal ändern _sollte_ bzgl. der Sonderzeichen, auf die sie allergisch reagiert - dann wird mysql_real_escape_string höchstvermutlich auch entsprechend angepasst; addslashes aber ziemlich sicher nicht, warum auch.

    1. Womit muß ich mich beschäftigen, wenn ich Sätze wie "Geben Sie dem User nur die Rechte für die Datenbank, die unbediungt nötig sind" lese?

    Mit dem Rechtesytem des DBMS :-)

    Wer nur Daten Lesen können soll, muss nicht Schreiben dürfen; wer in eine Tabelle Schreiben darf, muss das nicht unbedingt in _allen_ dürfen; ...

    GRANT/REVOKE sind Stich-/Schlüsselworte, zu denen das Handbuch Bescheid wissen sollte.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo wahsaga,

      danke, daß Du Dir die Zeit zum Antworten genommen hast. Dann werde ich mich mal an die Arbeit machen, eine entsprechende Anwendung schreiben und dann samt Quellcode hier zur Begutachtung posten.

      mfG

      Professor Hase

  2. Hallo Prof. Hase.

    Deine konkreten Fragen wurden dir ja schon ausführlich beanwortet.

    Als ich begonnen habe, mich mit html und CSS zu beschäftigen, mußte ich zwar auch öfters etwas nachlesen, im Grunde habe ich aber immer recht schnell verstanden, worum es geht, was die DO´S und DONT`S sind. Auch die ersten Gehversuche mit php selbst waren kein all zu großes Problem. Aber was die sichere Formularverarbeitung für eine Datenbank betrifft, sieht es leider anders aus. Je mehr Informationen ich diesbezüglich suche, egal ob hier oder woanders, umso verwirrter bin ich und umso mehr habe ich das Gefühl, _nichts_ zu verstehen.

    Ich selbst schreibe gerade auch mein erstes größeres Script in php+mysql und kann deine Probleme so ganz gut nachvollziehen. Was mir bisher eigentlich recht gut geholfen hat, war "das Analysieren" fremder Scripte zu bestimmten Zwecken, um dann, mithlfe von http://de3.php.net/manual/de/, einzelne Funktionen kennenzulernen und womöglich selbst zu verwenden.

    Zu magic_quotes_gpc kann ich noch eine Anmerkung machen:
    Ist man sich nicht sicher, wo das Script in Zukunft Verwendung finden wird (bzw. möchte man sich Korrekturen ersparen), bietet es sich an, vor einer Verwendung von mysql_real_escape_string abzufragen, ob magic_quotes_gpc ON oder OFF sind. So kann man doppelter Maskierung vorbeugen.

    MfG, Kungschu.

    --
    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.
    1. hi,

      Zu magic_quotes_gpc kann ich noch eine Anmerkung machen:
      Ist man sich nicht sicher, wo das Script in Zukunft Verwendung finden wird (bzw. möchte man sich Korrekturen ersparen), bietet es sich an, vor einer Verwendung von mysql_real_escape_string abzufragen, ob magic_quotes_gpc ON oder OFF sind. So kann man doppelter Maskierung vorbeugen.

      Auch das ist nicht ratsam.
      Für magic_quotes_gpc gilt das gleiche, was ich zu addslashes schrieb: Das mag _zufällig_ im Moment "ausreichend" sein, um Daten für die Nutzung in einer MySQL-Query zu entschärfen - _Garantie_ besteht dafür aber, insb. für die Zukunft, keine.

      Wenn
         magic_quotes_gpc an
      dann
         stripslashes.

      Danach
         weiter, wie üblich (also mysql_real_escape_string in diesem Falle).

      gruß,
      wahsaga

      --
      /voodoo.css:
      #GeorgeWBush { position:absolute; bottom:-6ft; }
      1. Hallo.

        Wenn
           magic_quotes_gpc an
        dann
           stripslashes.

        Danach
           weiter, wie üblich (also mysql_real_escape_string in diesem Falle).

        Da haben wir uns wohl falsch verstanden (bzw. ich nicht präzise genug formuliert). Genau das wollte ich damit sagen. Nicht etwa, dass eine Prüfung in manchem Fällen überflüssig sei, sondern dass vor einer Verwendung vom mysql_real_escape_string die doppelte Maskierung ausgeschlossen werden muss.

        MfG, Kungschu.

        --
        Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.
  3. echo $begrüßung;

    Ich werde jedenfalls versuchen, mit Hilfe des Forums so weit zu kommen, daß ich im Endeffekt einen _wirklich sicheren_ und dabei so schlank und einfach wie möglichen php-Code habe.

    Das wirst du nur bei übersichtlich kleinen Aufgabenstellungen erreichen können. Komplexere Dinge lassen sich kaum schlank realisieren. Hier kommt es darauf an, Einzelaufgaben an mehr oder weniger abgeschlossene Programmteile weiterzudelegieren. Diese sollten ihre Aufgabe eigenständig erledigen, also ohne zu spezielle Voraussetzungen an ihre Umgebung zu stellen. Insgesamt ist der Code zwar komplex, aber die Aufteilung soll ihn idealerweise so gestalten, dass die Übersicht gewahrt bleibt. Und wenn die Teilaufgaben geschickt umgesetzt wurden lassen sie sich in weiteren Projekten wiederverwenden und sparen so Entwicklungszeit.

    Im Allgemeinen hat es sich bewehrt, die drei Teile der EDV - Eingabe - Verarbeitung - Ausgabe - stets zu berücksichtigen, und sie am besten nicht miteinander zu vermischen. Beispiel: Magic Quotes und SQL-Maskierungen. Die Eingabedaten kommen, von den Magic Quotes verunstaltet, im Script an. An welcher Stelle sollen sie nun bereinigt werden? Man könnte eine Funktion schreiben, die neben dem Bereinigen gleich noch die SQL-Maskierung erledigt, also quasi ein um stripslashes() erweitertes mysql_real_escape_string(). Was ist nun, wenn die Daten nicht nur in die Datenbank geschrieben werden, sondern auch noch eine Kontrollausgabe auf dem Bildschirm erfolgen soll? Schreibt man sich da auch noch ein um stripslashes() erweitertes htmlspecialchars()? Und muss dann am Ende die Daten zweimal entmagicquotieren? Und obendrein hat man dann auch noch zwei Stellen, die man berücksichtigen muss, falls der slashstrippende Teil korrigiert werden muss. Besser ist es, die Daten an der Stelle zu bearbeiten, an der sie in das Programm eintreten, in dem Fall also am Scriptanfang *). Bearbeiten heißt hier, sie in ihre Rohform zu bringen, aus der sie dann im weiteren Verlauf der Verarbeitung die Ergebnisdaten berechnen lassen. Und die kann man dann kontextspezifisch nachbehandeln, wenn sie in einem bestimmten Kontext ausgegeben werden sollen.

    Für die vielen Fragen und Dummheiten meinerseites, die dabei sicher entstehen werden, bitte ich schon jetzt um Entschuldigung und Nachsicht. :-)

    Abgelehnt. Es ist ja nicht so, dass wir™ dir eine Hausaufgabe gestellt haben, und du dich nun entschuldigen musst, weil z.B. neben dem Besuch von Vergnügungseinrichtungen dafür nun überhaupt keine Zeit geblieben ist. Du versuchst dir Wissen über ein bestimmtes Thema anzueignen, hast dazu einige Fragen und zeigst dabei mehr Eigeninitiative als manch einer der Fragender hier. Das ist keinesfalls etwas, wofür man sich entschuldigen müsste.

    *) Das PHP-Handbuch hält auf der Seite Disabling Magic Quotes ein Beispiel (31.2) bereit, wie sich das einmal für alle GPC-Arrays erledigen lässt.

    echo "$verabschiedung $name";

  4. Hallo.

    DO´S

    Nó!

    DONT`S

    Nò!
    MfG, at