Kalle: Sicherheit von POST

Hallo,

Ich möchte meine Homepage sicherer machen!

Ich habe eine Datei an die ich alle post-Anfragen abgebe

post.php

foreach($_POST as $name => $value)
{
 $value = htmlspecialchars($value);
 $value = strip_tags($value);
 $valide[$name]=$value;
}

print "<pre>";
print_r($valide);
print "</pre>";

ist das eine Sichere Methode?
oder wie macht man das?

Kalle

  1. Mahlzeit Kalle,

    $value = htmlspecialchars($value);

    Warum an dieser Stelle? htmlspecialchars() solltest Du nur verwenden, wenn Du Werte im HTML-Kontext ausgeben willst, sonst nicht.

    ist das eine Sichere Methode?
    oder wie macht man das?

    Das kommt darauf an, was genau Du erreichen willst ...

    MfG,
    EKKi

    --
    sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
    1. Das kommt darauf an, was genau Du erreichen willst ...

      ei ich möchte mich vor Cross-Site-Scripting schützen.
      und da man im prinzip überall <b>was auch immer</b> eingeben kann ...

      Kalle

      1. Also ich habe ja eine extra post.php
        Welche $_SERVER-Variablen sollte ich wie abfragen um Sicher zu stellen, dass die Anfrage auf jeden Fall von der eigenen Seite ausgeführt wurde und nicht von einem anderen Server?

        Kalle

        1. ...ach dann mach ichs eben selbst...

          1. Mahlzeit Kalle,

            ...ach dann mach ichs eben selbst...

            Entschuldigen Durchlauchst bitte untertänigst, dass meine unwürdige Wenigkeit nicht Gewehr bei Fuß steht, um Ihro Gnaden Anforderungen umgehendst nachzukommen und sich stattdessen mit Nichtigkeiten wie "Geld verdienen" beschäftigt ...

            *PLONK*

            MfG,
            EKKi

            --
            sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
            1. Da muss auch ich mal lachen..
              Ich bin halt ein verdammt ungeduldiger Mensch
              Tschuldige!

              Kalle

        2. Mahlzeit Kalle,

          Welche $_SERVER-Variablen sollte ich wie abfragen um Sicher zu stellen, dass die Anfrage auf jeden Fall von der eigenen Seite ausgeführt wurde und nicht von einem anderen Server?

          Das geht nicht. Prinzipiell kann JEDER einen POST-Request an Deine Skripte schicken - vor allem werden es eher Browser (oder Browser nachahmende Skripte) sein und keine Server. Informiere Dich über die Grundlagen von HTTP.

          MfG,
          EKKi

          --
          sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
          1. Hello,

            Welche $_SERVER-Variablen sollte ich wie abfragen um Sicher zu stellen, dass die Anfrage auf jeden Fall von der eigenen Seite ausgeführt wurde und nicht von einem anderen Server?

            Das geht bedingt nur mit einer Session oder einem "Gutschein", den Du dem Besucher vorher auf einer anderen Seite zur Verfügung stellst. Es eignet sich dafür die Unique-Id, die der Apache automatisch zur Verfügung stellt, wenn Du das notwendige Modul installiert hast. Die kannst Du als Cookie (dann bleibt sie den Misten sicher verborgen) oder als Hidden-Field oder noch besser als Name des Submit-Buttons übermitteln.

            Auf dem Server merkst Du dir, dass diese ID ausgegeben wurde, aber noch nicht bearbeitet wurde.
            Wenn der nächste request mit der ID kommt, kannst Du sie als bearbeitet markieren, falls später noch ein Request damit kommt. Kommt überhaupt keine ID zurück, kannst Du davon ausgehen, dass der Besucher die Seite frisch aufgerufen hat oder neu begonnen hat...

            Kommen nur welche zurück, die beraits abgearbeitet sind, solltst Du dir die IP mal merken ;-)

            Liebe Grüße aus Syburg bei Dortmund

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. moment moment noch mal ganz langsam..

              Also ich habe das so verstanden, dass ich die session_id von session(); dazu nutze eine gültige post-anfrage senden zu dürfen.
              also hinterlege ich diese kombination in den submit-button. und jetzt? jetzt könnte ein angreifer immer noch die inputs manipulieren.

              das Sessions besser sind wie die GET-Methode oder Hidden-Felder habe ich begriffen. es ist nicht nur schöner sondern auch sicherer, da die variablen nicht überschrieben werden können.

              aber ich glaube die gutschein-methode habe ich noch nicht ganz kapiert.

              Und ist es tatsächlich möglich den $_SERVER["HTTP_REFERER"] zu manipulieren? ich dachte das ist eine SERVER-VAriable die mein SERVER erzeugt???
              [ SEHR WEIT AUSHOL ]
              Worauf kann man sich denn überhaupt noch verlassen?
              Warum gibt es so viele Sicherheitslücken?
              Ich sag euch: unsere Gesellscahft ist überhaupt noch nicht bereit für die Technologie von Heute. Die leute füllen ja immer noch Gewinnspiel-Zettel aus worauf auch stehen könnte: "Sie sind damit einverstanden 2 Esel im Wert von je 199,00 EUR zu kaufen" und 50% würden es machen. Was ich damit sagen will: das Internet ist zwar 2.0 und so weiter aber trotzdem noch in der BETA-Phase wenn ihr mich fragt!
              [ /SEHR WEIT AUSHOL ]

              und jetzt noch mal die Frage zu strip_tags():
              wenn ich <a> erlaube kann ich trotzdem eingeben:
              <a href="JavaScript:alert('Hallo');">test</a>
              und vorausgesetzt ich wende stripslashes() darauf an und gebe das ganze einfach aus könnte ich das javascript auch ausführen.

              "Diese Funktion modifiziert keine Attribute bei Tags, die via allowable_tags  erlaubt wurden, dies betrifft auch style und onmouseover Attribute, die ein böswilliger User verwenden kann, um einen Text zu posten, der von anderen Usern gesehen werden soll."

              Ein Feld in meinem Projekt soll HTML enthalten dürfen, ist das etwa ein ding der unmachbarkeit?

              Kalle

              1. Also ich habe das so verstanden, dass ich die session_id von session(); dazu nutze eine gültige post-anfrage senden zu dürfen.
                also hinterlege ich diese kombination in den submit-button. und jetzt? jetzt könnte ein angreifer immer noch die inputs manipulieren.

                Ja und?
                Wenn deine SessionId 76a8bb6b78cddca003673faf lautet, kann der lange raten.

                das Sessions besser sind wie die GET-Methode oder Hidden-Felder habe ich begriffen.

                Nö... Sessions in Urls sind allenfalls ein Problem.
                Oder die Form der SessionID, dann stellt sie aber auf jeden Fall ein Risiko dar.

                es ist nicht nur schöner sondern auch sicherer, da die variablen nicht überschrieben werden können.

                Cookies können jederzeit überschrieben werden. Alles ist manipulierbar.

                mfg Beat

                --
                Woran ich arbeite:
                X-Torah
                ><o(((°>      ><o(((°>
                   <°)))o><                      ><o(((°>o
                1. Also ich habe das so verstanden, dass ich die session_id von session(); dazu nutze eine gültige post-anfrage senden zu dürfen.
                  also hinterlege ich diese kombination in den submit-button. und jetzt? jetzt könnte ein angreifer immer noch die inputs manipulieren.

                  Ja und?
                  Wenn deine SessionId 76a8bb6b78cddca003673faf lautet, kann der lange raten.

                  Ach in den Submit button kommt nur der md5-Code der SessionID - das ist ne Idee! bzw. muss das nicht mal ne SessionID sein sondern irgendeine ID diese wird in der Mysql-Tabelle secure_posts eingetragen.

                  ID........(INT)
                  post_ids..(VarChar(20))
                  timestamp.(INT)

                  wird eine post_id verbraucht wird der Eintrag gelöscht.
                  timestamp dient für timeouts. alle Einträge die älter wie 10 Minuten sind werden gelöscht.

                  Kalle

                  1. Hello,

                    wird eine post_id verbraucht wird der Eintrag gelöscht.
                    timestamp dient für timeouts. alle Einträge die älter wie 10 Minuten sind werden gelöscht.

                    Wenn Du sie löschst, verschenkst Du ein gutes Stück Deiner möglichen Sicherheit.
                    Du musst sie nur ungültig kennzeichnen, am besten gleich mit einem RequestCounter.
                    Solange der 0 ist und die zugehörige Gültigkeitsdauer nicht abgelaufen, wird der Request bearbeitet, vorausgesetzt, er ist sonst plausibel. Kommt aber ein request auf eine ID, die schon einen Zählerstand größer 0 hat, und wiederholt sich dieser Vorgang trotz aussagefähiger Antwort mit passenden Links usw., versucht vermutlich jemand das System zu manipulieren...
                    Da kann man dann irgendwann anfangen zu loggen.

                    Unter passender Response verstehe ich übrigens sowas, wie die relativ neue Fehlerseite des Forums, wenn man sich versucht als registrierter User anzumelden ohne gültige Anmeldedaten. Meinen Glückwunsch an die DEVs. Das war lange überfällig.

                    Liebe Grüße aus Syburg bei Dortmund

                    Tom vom Berg

                    --
                    Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
                    1. Moin,

                      alle Einträge die älter wie 10 Minuten sind werden gelöscht.
                      Wenn Du sie löschst, verschenkst Du ein gutes Stück Deiner möglichen Sicherheit.
                      RequestCounter.
                      , versucht vermutlich jemand das System zu manipulieren...
                      Da kann man dann irgendwann anfangen zu loggen.

                      Das musste ich drei mal lesen, aber jetzt habe ich es vertsanden.
                      Der Nachteil ist dann aber das der Zufallsgenerator immer länger braucht bis er eine Freie ID gefunden hat.
                      Und wenn mein RequestCounter über 3 steigt fange ich an zu loggen.
                      Was sollte ich denn loggen? um damit auch vor "gericht" gehen zu können.

                      Außerdem stellst sich mir die Frage der Programmiertechnik in Bezug auf das matchen.

                      form.php:
                      function makeid(){
                       Eine ID wird generiert
                       Save ID to Mysql
                       Return ID
                      }
                        <INPUT TYPE=HIDDEN NAME="sichere_id" VALUE="<?=md5(makeid())?>"

                      #SUBMIT#

                      auswertung.php:
                      FOR-Schleife mit alle bisher generierten IDs durchgehen{
                       Dabei jede ID md5-verschlüsseln und mit  $sichere_id vergleichen
                       Wenn Match dann Return true
                      }

                      if (RETURN == true)
                      {
                       ...
                      }
                      else
                      {
                       HEADER("LOCATION: zurueck_mit_fehlermeldung");
                      }

                      Was mich an dieser Methode stört ist immer wieder alle IDs durchzu"schleifen".

                      1. Moin nochmal,

                        Diese Frage habe ich mal neu eröffnet:

                        Was sollte ich denn loggen? um damit auch vor "gericht" gehen zu können.

                        ?t=176766&m=1163523

                        Kalle

              2. Mahlzeit Kalle,

                Und ist es tatsächlich möglich den $_SERVER["HTTP_REFERER"] zu manipulieren? ich dachte das ist eine SERVER-VAriable die mein SERVER erzeugt???

                Ja. Aber aus Angaben, die ihm der Client mitteilt ("Ach übrigens, vorher war ich bei $anderer_Seite"). Auch hier gilt: ALL INPUT IS EVIL!

                [ SEHR WEIT AUSHOL ]
                Worauf kann man sich denn überhaupt noch verlassen?

                Auf nichts. Was war schon immer so und das wird auch so bleiben.

                Warum gibt es so viele Sicherheitslücken?

                Weil die Leute, die sich vor langer Zeit HTTP ausgedacht haben, nicht damit gerechnet haben, dass ganze sicherheitskritische Anwendungen über dieses einfach gestrickte Protokoll abgewickelt werden sollen.

                Ich sag euch: unsere Gesellscahft ist überhaupt noch nicht bereit für die Technologie von Heute.

                Wenn Du es genau nimmst, ist das eher Technologie von gestern.

                das Internet ist zwar 2.0 und so weiter aber trotzdem noch in der BETA-Phase wenn ihr mich fragt!

                Technisch ist es immer noch 0.1 ...

                MfG,
                EKKi

                --
                sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
              3. Hi,

                und jetzt noch mal die Frage zu strip_tags():
                wenn ich <a> erlaube kann ich trotzdem eingeben:
                <a href="JavaScript:alert('Hallo');">test</a>
                und vorausgesetzt ich wende stripslashes() darauf an und gebe das ganze einfach aus könnte ich das javascript auch ausführen.

                Du machst einen Denkfehler: PHP setzt weder HTML-Code um noch führt es Javascript aus und auch Slashes in Strings sind zunächst einfach nur Zeichen. Daher ist es unsinnig, die Daten pauschal zu verstümmeln und dann so abzuspeichern.
                Die Rohdaten müssen nur im jeweiligen Kontext passend abgesichert werden. In bestimmten Fällen bei der Übergabe an PHP-Funktionen über addslashes(), an mySQL-Queries über mysql_real_escape_string(), und für die HTML-Ausgabe über htmlspecialchars().

                strip_tags() ist in aller Regel unpassend, denn diese Funktion greift sich alles fast zwischen <>, auch harmlose Texte, die zufällig so vom übrigen Text abgegrenzt werden.
                echo htmlspecialchars("<Test>") hingegen gibt diesen Text aus, ohne dass Browser versuchen, HTML-Code umzusetzen.

                Ein Feld in meinem Projekt soll HTML enthalten dürfen, ist das etwa ein ding der unmachbarkeit?

                nö. Dazu gibt es zwei Möglichkeiten:
                1. BBcode
                2. Manuelle Ersetzung aller unerwünschten Tags

                freundliche Grüße
                Ingo

  2. Hello,

    post.php

    foreach($_POST as $name => $value)
    {

    Was ist mit Rekursion für mehrwertige Parameter?
    Es ist ohne weiteres möglich, dass ein Parameter sich als "Array" darstellt und selber auch wieder "Arrays" enthält.

    $value = htmlspecialchars($value);
    $value = strip_tags($value);

    Warum entfernst Du etwas, was Du eine Zeile vorher gerade eingefügt hast?

    $valide[$name]=$value;

    Auch Parameternamen können Unsinn enthalten, da sie ja von außen kommen.

    }

    print "<pre>";

    // hier wäre nun die Anwendung von htmlspecialchars(print_r($_POST,1)) angemessen

    print_r($valide);
    print "</pre>";

    ist das eine Sichere Methode?

    Wofür? Deinen Prozessor mit Unsinn zu beschäftigen?
    Was willst Du denn mit den übernommenen Daten anfangen?
    Ein paar Kleiner-Zeichen oder Größer-Zeichen im übermittelten Text stellen noch keinen Angriff dar.

    Du hast die eventuell notwendige Behandlung von Magic Quotes nicht berücksichtigt.

    Wenn get_magic_quotes_gpc() gesetzt ist, dann musst Du diese Quotes vermutlich erst wieder entfernen, um an die Rohdaten zu gelangen.

    Liebe Grüße aus Syburg bei Dortmund

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de