Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Formulareingaben prüfen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Formulareingaben prüfen

    Hallo, meine nächste Frage.

    Es geht um Kontrolle von User-Eingaben in Formularfelder (input text, textarea, checkbox usw.).

    Laut Wissenssammlung reicht strip_tags zum Schutz aus:
    Eine Möglichkeit, XSS zu verhindern, ist die Entfernung aller Tags mit strip_tags. Dies ist die empfohlene Vorgehensweise, wenn es sich um Daten handelt, in denen HTML nichts zu suchen hat (etwa Angabe des Namens, der Adresse oder der Telefonnummer).
    Erste Frage:

    Was ist der Unterschied zwischen strip_tags und
    PHP-Code:
    filter_var($_POST['eintrag'], FILTER_SANITIZE_STRING
    ?
    Ich bei Tests nur festgestellt, dass filter_var... zusätzlich die Quotes umwandelt.

    Zweite Frage:

    Reicht das auch, wenn die Eingaben auch in eine Datenbank eingetragen werden (INSERT, UPDATE)? Oder sollte hier noch
    PHP-Code:
    VALUES ('".htmlentities($eintrag)."'
    // oder
    VALUES ('".htmlspecialchars($eintrag)."' 
    hinzu.

    Dritte Frage (in bin ein Ungläubiger):

    Sind weitere Zeichen (z.B. %, !, ?, >, -) bei INSERT bzw. UPDATE unschädlich?
    Ich hab's mal getestet (mit htmlentities). Der Eintrag in der DB sieht so aus:
    Code:
    "Test" mit
        Leerzeichen!!!
    % prozent
    - Bindestrich
    > eckige Klammer
    ; Semikolon
    ? fragezeichen
    @ Klammeraffe
    Umgewandelt wurde also nur "" und >
    Warum wandelt htmlentities diese Zeichen nicht um? Für die gibt es ja HTML-Maskierungen.
    Die wichtigste Frage ist natürlich, ob das ein Sicherheitsproblem darstellt?
    Wie immer danke schon mal für gute Tipps!


  • #2
    http://wiki.selfhtml.org/wiki/PHP/An...Kontextwechsel

    Kommentar


    • #3
      Zitat von HeinrichK Beitrag anzeigen
      Was ist der Unterschied zwischen strip_tags und
      PHP-Code:
      filter_var($_POST['eintrag'], FILTER_SANITIZE_STRING
      http://php.net/manual/en/filter.filters.sanitize.php

      http://php.net/manual/de/function.strip-tags.php

      LG
      Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
      PHP.de Wissenssammlung | Kein Support per PN

      Kommentar


      • #4
        @tk1234

        Es ist ja gerade der Kontextwechsel, den ich bearbeiten will - auch wenn ich nicht in jedes Posting "Kontextwechsel" reinschreibe.

        Ein Hinweis auf einen Artikel, den ich schon gelesen habe, hilft mir weniger, als wenn du auf meine Fragen eingehen würdest (ich weiß, es ist spät am Abend).

        @hausl

        Die beiden Links habe ich auch durchgelesen. Deshalb weiß ich, dass FILTER_SANITIZE_STRING (zusätzlich zu strip_tags) auch "special characters" codiert, und will meine Frage präzisieren:
        Macht FILTER_SANITIZE_STRING auch alles, was strip_tags macht? Auch "NUL Bytes" entfernen?

        Danke an euch und an weitere Tipps!

        Kommentar


        • #5
          Es ist ja gerade der Kontextwechsel, den ich bearbeiten will - auch wenn ich nicht in jedes Posting "Kontextwechsel" reinschreibe.
          Du machst gefühlt mal wieder alles, außer Kontextwechsel korrekt zu bearbeiten… Das liegt aber nicht nur an dir. (Siehe unten.)

          Deshalb weiß ich, dass FILTER_SANITIZE_STRING (zusätzlich zu strip_tags) auch "special characters" codiert
          Wenn du die entsprechende FLAG_* dazu beim Aufruf übergibst.

          Macht FILTER_SANITIZE_STRING auch alles, was strip_tags macht?
          Scheint so.

          PHP-Code:
          $input "\x00";
          $tmp filter_var($inputFILTER_SANITIZE_STRING);
          var_dump(strlen($tmp)); // int(0) 
          Laut Wissenssammlung reicht strip_tags zum Schutz aus:

          Eine Möglichkeit, XSS zu verhindern, ist die Entfernung aller Tags mit strip_tags. Dies ist die empfohlene Vorgehensweise, wenn es sich um Daten handelt, in denen HTML nichts zu suchen hat (etwa Angabe des Namens, der Adresse oder der Telefonnummer).
          Das ist unter den meisten Umständen (wenn der Inhalt nicht in bestimmten HTML-Attributen landet) nicht falsch, hat aber an der Stelle nichts mit dem Kontextwechsel zu tun. (Ich formuliere das dort nachher mal ein wenig um.)

          Daten in HTML-Code eintragen: htmlspecialchars (htmlentities geht auch, ist aber nahezu immer übertrieben) – jeweils mit ENT_QUOTES
          Daten in SQL-Queries eintragen: je nach Adapter zum Beispiel mysql_real_escape_string (veraltet), mysqli_real_escape_string, PDO::quote oder auch Prepared Statements

          Wenn zudem Daten in bestimmte HTML-Attribute (a.href etwa) eingetragen werden, ist neben htmlspecialchars gegebenenfalls noch weitere Validierung notwendig, um zu verhindern, dass dort JavaScript-Code landet.

          Reicht das [FILTER_SANITIZE_STRING] auch, wenn die Eingaben auch in eine Datenbank eingetragen werden (INSERT, UPDATE)?
          Nein, das reicht nicht.

          Daten in HTML-Code eintragen: htmlspecialchars (htmlentities geht auch, ist aber nahezu immer übertrieben) – jeweils mit ENT_QUOTES
          Daten in SQL-Queries eintragen: je nach Adapter zum Beispiel mysql_real_escape_string (veraltet), mysqli_real_escape_string, PDO::quote oder auch Prepared Statements

          Oder sollte hier noch
          PHP-Code:
          VALUES ('".htmlentities($eintrag)."'
          // oder
          VALUES ('".htmlspecialchars($eintrag)."' 
          hinzu.
          Nein.

          Daten in HTML-Code eintragen: htmlspecialchars (htmlentities geht auch, ist aber nahezu immer übertrieben) – jeweils mit ENT_QUOTES
          Daten in SQL-Queries eintragen: je nach Adapter zum Beispiel mysql_real_escape_string (veraltet), mysqli_real_escape_string, PDO::quote oder auch Prepared Statements

          Sind weitere Zeichen (z.B. %, !, ?, >, -) bei INSERT bzw. UPDATE unschädlich?
          Wenn du die Kontextwechsel richtig behandelst, ist jedes Zeichen unschädlich.

          Daten in HTML-Code eintragen: htmlspecialchars (htmlentities geht auch, ist aber nahezu immer übertrieben) – jeweils mit ENT_QUOTES
          Daten in SQL-Queries eintragen: je nach Adapter zum Beispiel mysql_real_escape_string (veraltet), mysqli_real_escape_string, PDO::quote oder auch Prepared Statements

          Ich hab's mal getestet (mit htmlentities).
          Was an der Stelle unsinnig ist.

          Escape-Sequenzen für einen bestimmten Ausgabekontext haben in der DB in aller Regel nichts verloren, weil du beim DB-Eintrag noch nicht weißt, in welcher Form du die Daten schließlich ausgeben willst. Neben HTML wäre ja beispielsweise auch CSV oder PDF oder dergleichen denkbar.

          Ansonsten: Du weißt schon.

          Warum wandelt htmlentities diese Zeichen nicht um? Für die gibt es ja HTML-Maskierungen.
          Und zwar?

          Ansonsten: Die liegen in 7-Bit-ASCII und haben keine syntaktische Relevanz.

          htmlentities wandelt für ENT_COMPAT | ENT_HTML401 und UTF-8 diese Zeichen um:

          PHP-Code:
          var_dump(get_html_translation_table(HTML_ENTITIESENT_COMPAT ENT_HTML401'UTF-8')); 
          Die wichtigste Frage ist natürlich, ob das ein Sicherheitsproblem darstellt?
          Wenn du die Kontextwechsel passend behandelst und keine Logik programmierst wie if ($eingabe === 'hallo') { ZerstöreAlles }, dann stellt kein Zeichen ein Sicherheitsproblem dar.

          Kommentar


          • #6
            Hallo mermshaus,

            danke für deinen auführlichen Beitrag! Puh, ich versuche mal, für mich zu sortieren.

            Ich hatte die Wissenssammlung und selfhtml-wiki so verstanden, dass ein Kontextwechsel vorliegt, u.a. wenn

            1. Teile der URL (Querystring) in PHP-Variablen eingehen ($_GET)
            > Behandlung mit z.B. strip_tags
            2. PHP-Variablen in ein MYSQL-Statement eingehen
            > in der WHERE-Klausel mit mysql_real_escape_string maskieren

            Meine Unsicherheit liegt bei
            3. PHP-Variablen gehen in den INSERT- oder UPDATE-Teil des Statements ein.
            Vielleicht ist wichtig, was ich damit tue. Daten aus INPUT / TEXTAREA werden per POST ans Script geschickt und zu PHP-Variablen (Behandlung wie 1.) Von dort werden sie per INSERT in die DB eingetragen.

            Nun sagst du, strip_tags (Schritt 1) reicht nicht, aber htmlenties/specialchars sei an dieser Stelle falsch...

            Aber mysql_real_escape_string kann's an dieser Stelle doch auch nicht sein. Einen hinzugefügten slash könnte ich ja bei der Ausgabe (aus DB von PHP-Script in html eingefügt) noch stripslashen.
            Aber es gibt ja einen Admin-Bereich, in welchem alle diese Einträge editiert werden. Wenn ich nun dreimal ändere (UPDATE set text = '".mysql_real_escape_string($text)."'), habe ich schon drei Slashes drin.

            ===> ich denke gerade beim Schreiben: Ich könnte mir den Eintrag mit stripslashes($text) aus der DB holen; dann ging's, oder? <===

            Aber was spricht gegen die html-Maskierung, wenn die Einträge zu keinem anderen Zweck gespeichert werden, als sie wieder im Browser auszugeben? Der CKEditor macht das genauso (ob der Probleme hat, ist ein späteres Thema).

            erstmal soviel. Ich freue mich über weitere Hilfestellung.

            Kommentar


            • #7
              Zitat von HeinrichK Beitrag anzeigen
              1. Teile der URL (Querystring) in PHP-Variablen eingehen ($_GET)
              > Behandlung mit z.B. strip_tags
              Nein. PHP macht aus dem Querystring automatisch die Werte in $_GET, das ist kein Kontextwechsel. Relevant wird es erst wenn du die Werte aus $_GET in irgendeiner Form ausgibst oder z.B. an die Datenbank schickst.

              2. PHP-Variablen in ein MYSQL-Statement eingehen
              > in der WHERE-Klausel mit mysql_real_escape_string maskieren
              Jein. alles was du an Daten in ein Query schreibst muss maskiert werden, nicht nur das was im WHERE-Teil steht.

              Meine Unsicherheit liegt bei
              3. PHP-Variablen gehen in den INSERT- oder UPDATE-Teil des Statements ein.
              Vielleicht ist wichtig, was ich damit tue. Daten aus INPUT / TEXTAREA werden per POST ans Script geschickt und zu PHP-Variablen (Behandlung wie 1.) Von dort werden sie per INSERT in die DB eingetragen.

              Nun sagst du, strip_tags (Schritt 1) reicht nicht, aber htmlenties/specialchars sei an dieser Stelle falsch...
              htmlspecialchars() ist für den Kontextwechsel nach HTML, strip_tags() hat mit Kontextwechsel nichts zu tun. Und für Daten in Querys, siehe oben: völlig egal ob das ein SELECT-, INSERT-, UPDATE- oder WASWEISICH-Query ist, Daten werden immer mit mysqli_real_escape_string() (bzw. entsprechenden Funktionen/Methoden) behandelt.

              Aber mysql_real_escape_string kann's an dieser Stelle doch auch nicht sein. Einen hinzugefügten slash könnte ich ja bei der Ausgabe (aus DB von PHP-Script in html eingefügt) noch stripslashen.
              Ein Slash stört HTML nicht, warum möchtest du ihn entfernen? Oder meinst du Magic Quotes? Die sind mit PHP 5.4 ohnehin Geschichte ...

              Aber es gibt ja einen Admin-Bereich, in welchem alle diese Einträge editiert werden. Wenn ich nun dreimal ändere (UPDATE set text = '".mysql_real_escape_string($text)."'), habe ich schon drei Slashes drin.
              Du meinst wenn in $text z.B. das: »foo \" bar« steht? Der Query sieht dann so aus: »UPDATE set text = 'foo \\\" bar'«, das ist richtig - allerdings, wie schon geschrieben: magic_quotes gibt es nicht mehr, wenn du noch eine veraltete PHP-Version einsetzt musst du hier u.U. erst noch die Slashes entfernen die von PHP hinzugefügt werden.

              Aber was spricht gegen die html-Maskierung, wenn die Einträge zu keinem anderen Zweck gespeichert werden, als sie wieder im Browser auszugeben?
              Vielleicht brauchst du es jetzt nicht für einen anderen Zweck - aber weißt du ob du die Einträge nicht doch mal anderweitig ausgeben willst? Behandle immer nur genau den Kontextwechsel der gerade vorliegt, niemals irgendeinen der möglicherweise später irgendwann mal auftritt.

              Kommentar


              • #8
                @tk1234

                ich hoffe / glaube, du und mermshaus habt mir nun die strukturelle Erleuchtung gebracht. Also...

                Von PHP in die DB immer maskieren, z.B.
                PHP-Code:
                "UPDATE ".TAB_GB."  SET vorname ='".mysql_real_escape_string($vorname)."' WHERE id='".mysql_real_escape_string($id)."';" 
                Von DB in PHP - Slashes entfernen, z.B.
                PHP-Code:
                $vorname stripslashes($zeile->vorname); 
                Von PHP in HTML-Kontext, z.B.
                PHP-Code:
                <b>".htmlspecialchars($vorname)."</b
                So klappt das auch beim Editieren von Einträgen.

                Also, sagt mal - hab ich's verstanden?

                Kommentar


                • #9
                  Fast. Je nachdem was id für ein Feld ist, ist quoting und escaping verkehrt.
                  http://www.php.de/php-einsteiger/112...tml#post831289

                  Ich kanns nur wiederholen: Nutz bei der Datenbank Prepared Statements. Dann kann dir das Zeug egal sein. Dazu gleich zum Lesen: http://stackoverflow.com/questions/8...red-statements

                  Zitat von mermshaus Beitrag anzeigen
                  Daten in HTML-Code eintragen: htmlspecialchars (htmlentities geht auch, ist aber nahezu immer übertrieben) – jeweils mit ENT_QUOTES
                  In wie fern übertrieben?
                  edit: nvm, paar Beispiele gefunden: http://stackoverflow.com/questions/4...mlspecialchars
                  Relax, you're doing fine.
                  RTFM | php.de Wissenssammlung | Datenbankindizes | Dateien in der DB?

                  Kommentar


                  • #10
                    Fast richtig, nur:
                    Zitat von HeinrichK Beitrag anzeigen
                    Von DB in PHP - Slashes entfernen, z.B.
                    PHP-Code:
                    $vorname stripslashes($zeile->vorname); 
                    Nein, DB->PHP ist kein Kontextwechsel der zu behandeln wäre, mit stripslashes() würdest du deine Daten verfälschen.

                    Kommentar


                    • #11
                      K, hab von DB -> PHP übersehen.
                      Und nach dem Blick über PHP -> HTML:
                      PHP-Code:
                      <b>".htmlspecialchars($vorname)."</b
                      Daten in HTML-Code eintragen: htmlspecialchars (htmlentities geht auch, ist aber nahezu immer übertrieben) – jeweils mit ENT_QUOTES
                      Ergibt:
                      PHP-Code:
                      <b>".htmlspecialchars($vorname, ENT_QUOTES)."</b
                      Relax, you're doing fine.
                      RTFM | php.de Wissenssammlung | Datenbankindizes | Dateien in der DB?

                      Kommentar


                      • #12
                        @VPh

                        $id ist ein Integer. Wird über den Querystring übergeben und schon mal "behandelt"
                        PHP-Code:
                        $id intval($_GET['id']; 
                        Laut mermshaus (wie ich ihn verstanden habe) sollen trotzdem alle Daten beim Einfügen in ein MYSQL-Statement maskiert werden.

                        Prepared Statements - das werde ich tun, brauche aber Zeit, die ich als Hobby-Webmacher gerade nicht habe. Jetzt geht es mir nur darum, die bestehende Sache sicher zu machen.

                        Ah ja, danke - das htmlspecialchars($vorname, ENT_QUOTES) hatte ich auch übersehen.

                        @TK1234

                        Ohne stripslashes wird mir der Text im Browser mit /" ausgegeben. Kann es sein, dass mir magic_quotes dazwischen funkt? (Die Seite läuft bei meinem Hoster unter PHP 5.3. und möglich wäre dort zur Zeit noch 5.4)

                        Jetzt aber nochmal zum "Kontextwechsel",
                        > der vorliegt wenn
                        - PHP in MySQL-Statement?
                        - PHP in HTML?
                        - wann noch?
                        > der nicht vorliegt, wenn
                        - DB in PHP?
                        - Querystring in PHP?

                        So fasse ich zumindest die Beiträge in diesem Thread auf....

                        Kommentar


                        • #13
                          Zitat von HeinrichK Beitrag anzeigen
                          Ohne stripslashes wird mir der Text im Browser mit /" ausgegeben. Kann es sein, dass mir magic_quotes dazwischen funkt?
                          Vermutlich, ja. stripslashes() musst du dann allerdings schon auf die Daten anwenden bevor du sie irgendwie weiterverarbeitest (z.B. in der Datenbank speicherst), nur so bekommst du wieder deine Originaldaten. btw: magic_quotes lässt sich auch abschalten.

                          (Die Seite läuft bei meinem Hoster unter PHP 5.3. und möglich wäre dort zur Zeit noch 5.4)
                          Das wäre der sinnvollere Weg, PHP 5.3 wird ohnehin nicht mehr unterstützt.

                          Jetzt aber nochmal zum "Kontextwechsel",
                          > der vorliegt wenn
                          - PHP in MySQL-Statement?
                          - PHP in HTML?
                          - wann noch?
                          Siehe Fortsetzung zu dem in #2 verlinkten Artikel, z.B. PHP in URL, Javascript oder auch Kombinationen aus HTML/URL/JS o.ä..

                          Kommentar


                          • #14
                            @TK1234

                            Das ist sicher sinnvoll. Ich muss nur schauen, wie ich das - mit meinen veralteten Seiten - umsetze. Zur Zeit arbeite ich auf "offener See". Will heißen an den öffentlich laufenden Webseiten. Da will ich nix unnötig zerschießen.

                            Ich werde mir einen lokalen Testserver installieren (xampp) und dort die Seiten neu aufbauen, bevor sie online gehen. Da ich aber in Kürze einen neuen PC haben werde, will ich's erst dann tun.

                            Dann finden auch die Hinweise auf "weitere" Kontextwechsel Berücksichtigung. Ich denke, ich kann diesen Thread jetzt schließen.

                            Es folgen aber noch Fragen zu anderen Themen (neuer Thread)...

                            Kommentar


                            • #15
                              Zitat von HeinrichK Beitrag anzeigen
                              Ich werde mir einen lokalen Testserver installieren (xampp) und dort die Seiten neu aufbauen, bevor sie online gehen.
                              Ich würde als lokale Testumgebung kein xampp verwenden sondern die einzelnen Komponenten (Apache, PHP, MySQL) einzeln installieren - und zwar in den Versionen die auch beim Provider laufen.

                              Kommentar

                              Lädt...
                              X