ChrisL: Sicherheit, Code Injections u.ä.

Hallo Forum

Bin PHP Anfänger und programmiere eine Art Content Management System. Habe mich nun erstmals in das Thema Sicherheit eingelesen und würde mich freuen, wenn jemand meine Schlussfolgerungen anschaut, um sicher zu gehen, dass ich nichts wichtiges überschaut habe.

Also erstmal habe ich Textfelder, die ich per POST übergebe. Die Textfelder sind reine Texteingaben, einmal normal und einmal mehrzeilig. Ich denke hier braucht es den Befehl strip_tags() und zusätzlich bei mehrzeilig nl2br().

Bei einem spezifischen Fehler (rest ist mit JavaScript plausibilisiert) kommen die Daten mit GET wieder zurück ins Formular. Ich denke hier brauchts nur br2nl() bei mehrzeilig.

OK, dann kommen die Daten in eine SQL Datanbank. Hierfür mysql_real_escape_string(). Habe gelesen, wenn die Server Funktion magic_quotes_gpc auf ON ist (bei mir der Fall), muss vorher noch stripslashes() angewendet werden.

Schliesslich lese ich die Daten in der SQL-DB und gebe diese aus. Hierfür zuerst addslashes() (weil vorher entfernt) und dann noch htmlspecialchars().

Könnt ihr mir sagen, ob das soweit richtig ist oder ob was wichtiges fehlt? Bin um jeden Hinweis und Kommentar dankbar.

Gruss
Chris

PS: Ich verstehe auch, dass man zum Thema Sicherheit ganze Bücher schreiben könnte und sehr viele andere Aspekte auch zu berücksichtigen sind, aber möchte halt wissen, ob ich mich total auf dem Holzweg befinde oder nicht.

PPS: Ich verwende übrigens keine POST/GET Variablen direkt als include(). Habe gelesen das wäre gefährlich.

  1. Hello Chris L.,

    Bin PHP Anfänger und programmiere eine Art Content Management System. Habe mich nun erstmals in das Thema Sicherheit eingelesen und würde mich freuen, wenn jemand meine Schlussfolgerungen anschaut, um sicher zu gehen, dass ich nichts wichtiges überschaut habe.

    Ich weiß, man will immer gleich 'was Großes anstreben, aber fang doch erstmal mit den Basics an:

    1. Einfache Ausgaben, Daten aus Textdateien HTML-gerecht aufbereiten und ausgeben

    2. Post und Get mit Formularen und URi, Daten auis dem Request übernehmen und dann
       als Response HTML-gerecht darstellen in HTML/plain, Tabellen, Input-Elementen,
       usw.

    3. Zähler aufbauen und anzeigen, Arbeiten mit Datei, was ist eine Race-Condition?

    4. Das Affenformular, _der_ Meilenstein in der Lernhistorie eines Webprogrammierers

    5. Umgang mit Dateien, Gästebuch schreiben, mehrseitige Formulare, Überprüfungen
       von Eingaben, Stringfunktionen, Ersetzungsfunktionen, Einfügen in Dateien (z.B.
       Admin-Kommentare im Gästebuch), Dateiformate, usw.

    6. Datenbanknutzung

    und dann solltest Du langsam laufen können... :-))

    Also erstmal habe ich Textfelder, die ich per POST übergebe. Die Textfelder sind reine Texteingaben, einmal normal und einmal mehrzeilig.

    Stelle diese in der response-Seite dar und schau Dir an, was passiert

    Ich denke hier braucht es den Befehl strip_tags()

    Das kommt auf den Sinn an, den die Eingaben haben sollen. Wenn jemand über die Textbox HTML-text erfassen will/soll, dann wäre es doch unsinnig, die eingegebenen Daten (Tags) zu entfernen.
    Versuche als erstes, Daten unverändert nutzbar zu machen.

    Um Daten, die HTML-Zeichen enthalten können, wieder im HTML-Kontext ausgeben zu können, benötigst Du nur die Funktion htmlspecialchars() http://de2.php.net/manual/en/function.htmlspecialchars.php
    und die Angabe, dass es sich um Preformatted Text handelt <pre> ...  </pre>

    und zusätzlich bei mehrzeilig nl2br().

    Wenn Du den text dann HTML-formatiert ausgeben willst, sind die Funktionen

    nl2br()    http://de2.php.net/manual/en/function.nl2br.php
       wordwrap() http://de2.php.net/manual/en/function.wordwrap.php

    zusätzlich zu htmlspecialchars() http://de2.php.net/manual/en/function.htmlspecialchars.php
    nützlich.

    Bei einem spezifischen Fehler (rest ist mit JavaScript plausibilisiert) kommen die Daten mit GET wieder zurück ins Formular. Ich denke hier brauchts nur br2nl() bei mehrzeilig.

    Die Funktion kenne ich nicht und warum Du jetzt auch schon anfängst, JavaScript ins Spiel zu bringen, wo Du gerade erst PHP lernen willst, verstehe ich auch nicht.

    Ob die Daten als GET- oder als POST-Parameter übergeben werden, hängt von der Gestaltung des Sokumentes und vom Verhalten des Users ab. Ins "Formular" kommen sie aber immer nur durch die Art der Programmierung auf dem Server und werden mit diesem zusammen als HTTP-Response auf einen Request ausgeliefert. Was dann am Client damit geschieht, liegt nicht im Einflussbereich des PHP-Programmes.

    OK, dann kommen die Daten in eine SQL Datanbank. Hierfür mysql_real_escape_string(). Habe gelesen, wenn die Server Funktion magic_quotes_gpc auf ON ist (bei mir der Fall), muss vorher noch stripslashes() angewendet werden.

    Schalt doch Magic Quotes einfach ab. Das geht auch oft in einer .htaccess-Datei oder einer eigenen php.ini, je nachdem, ob PHP als Modul oder als CGI läuft.

    Schliesslich lese ich die Daten in der SQL-DB und gebe diese aus. Hierfür zuerst addslashes() (weil vorher entfernt) und dann noch htmlspecialchars().

    Warum willst Du etwas Unsinniges wieder hinzufügen, was Du vorhin gerade mühevoll entfernt hast?

    Könnt ihr mir sagen, ob das soweit richtig ist oder ob was wichtiges fehlt?

    Übung, Übung, Übung...

    Harzliche Grüße vom Berg
    http://bergpost.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

    1. Hallo Tom

      Vielen Dank für die sehr ausführliche Antwort. Ich arbeite mich hier mal durch und melde mich ggf. nochmals.

      Ich weiss deine Bemühungen sehr zu schätzen.

      Gruss
      Chris

  2. Hallo,

    Also erstmal habe ich Textfelder, die ich per POST übergebe. Die Textfelder sind reine Texteingaben, einmal normal und einmal mehrzeilig. Ich denke hier braucht es den Befehl strip_tags() und zusätzlich bei mehrzeilig nl2br().

    diese Funktionen brauchst du nur bei der Ausgabe über HTML.
    Wobei du dir strip_tags sogar sparen kannst.

    Bei einem spezifischen Fehler (rest ist mit JavaScript plausibilisiert) kommen die Daten mit GET wieder zurück ins Formular. Ich denke hier brauchts nur br2nl() bei mehrzeilig.

    br2nl() gibt es nicht.
    Wenn du die Daten wieder ins Feld setzen willst, gehe so vor <textarea name="text"...><?PHP echo htmlspecialchars($_GET['text']) ?></textarea> (die Zeilenumbrüche bleiben erhalten)

    Vorher sollte mit den Daten nichts passieren.

    Wenn du die Daten in eine DB speichern willst, gehe so vor
    "INSERT .... '".mysql_real_escape_string($_GET['text'])."' " (die Zeilenumbrüche bleiben erhalten)

    Vorher sollte mit den Daten nichts passieren.

    Wenn du die Daten per html ausgeben willst, gehe so vor
    echo nl2br(htmlspecialchars($textWoherAuchImmer));

    Vorher sollte mit den Daten nichts passieren.

    Du siehst, die Daten bleiben in ihrem Ursprünglichen Zustand und werden erst bei der Ausgabe in den entsprechenden Kontext gesetzt.
    Es ist einfach blödsinn irgendwelche Daten mit htmlspecialchars(), nl2br() o.ä. z.B. in einer Datenbank zu speichern.
    Kurz gesagt, willst du die Daten für HTML aufbereiten verwende htmlspecialchars() und niemand kann etwas 'böses' anstellen.
    Willst du sie in eine DB speichern verwende mysql_real_escape_string(),
    willst du sie innerhalb von PHP weiter verwenden benutze addslashes().

    Nicht vergessen die Magic Quotes zu deaktivieren.

    Grüße, Matze

    1. echo $begrüßung;

      willst du sie innerhalb von PHP weiter verwenden benutze addslashes().

      Könntest du dazu bitte eine Begründung angeben?

      echo "$verabschiedung $name";

      1. Hallo,

        willst du sie innerhalb von PHP weiter verwenden benutze addslashes().

        Könntest du dazu bitte eine Begründung angeben?

        Stimmt, die Funktion ist zur Kommunikation mit Datenbanken gedacht.

        Grüße, Matze

        1. Hi,

          willst du sie innerhalb von PHP weiter verwenden benutze addslashes().

          Könntest du dazu bitte eine Begründung angeben?

          Stimmt, die Funktion ist zur Kommunikation mit Datenbanken gedacht.

          lass Dich nicht ins Boxhorn jagen. Sofern es eine MySQL-Datenbank ist, sollte stets mysql_real_escape_string() verwendet werden. Sie bewirkt zwar noch das gleiche wie adslashes(), aber was meinst Du, warum es diese Funktion überhaupt gibt und warum sie so benannt wurde? Sollten in MySQL einmal weitere Maskierungen nötig werden, dann wären alle Scripte mit addslashes() veraltet und unsicher...

          freundliche Grüße
          Ingo

          1. echo $begrüßung;

            Sofern es eine MySQL-Datenbank ist, sollte stets mysql_real_escape_string() verwendet werden. Sie bewirkt zwar noch das gleiche wie adslashes(),

            Nicht ganz. addslashes() behandelt nur ', ", \ und \x0. mysql_(real_)escape_string() berücksichtigt außerdem auch \n, \r und \x1a. (Weiterhin berücksichtigt die real-Variante noch die Kodierung der aktuellen MySQL-Verbindung, was aber für die in der westlichen Welt hauptsächlich verwendeten Kodierungen ISO-8859-X und UTF-8 keinen Unterschied ergibt.)
            addslashes() fängt zwar schon mal das Gröbste ab, aber eben nicht alles.

            echo "$verabschiedung $name";

            1. Danke auch an Ingo und Matze. Muss ich jetzt alles erstmal genau studieren und verdauen.

            2. Hallo,

              addslashes() fängt zwar schon mal das Gröbste ab, aber eben nicht alles.

              sollte eigentlich, aber PHP halt.
              Das kann man aber sicher so interpretieren, dass die Datenbank eher weiß was sie will, als PHP ^^
              Also Kontext beachten :)

              Grüße, Matze