g-force: cgi Daten serverseitig begrenzen?

Hi Selfhtml-Forum

Ich möchte ein einfaches Gästebuch selber schreiben. Dazu brauche ich ein Formular, ein serversitiges Script und eine Datei, in der ich die Einträge speichere.

Soweit - so gut.

Das Formular bekomt:

-Ein Feld in dem der Gast seinen Namen einträgt, der seinem Texteintrag zugeordnet wird.

-Es bekomt ein Checkbottom, mit dem er sich einverstanden erklärt die Gästebuchregeln an zu erkennen.

-Ein Textfeld mit einer limitierten Anzahl von Zeichen.

-Und einen "Absende"-Knopf, mit dem er seine Nachricht veröffentlichen kann.

Um zu vermeiden, das "unendlich" viel Text übertragen wird, welcher ja Speicherplatz auf dem Server belegt, wollte ich die Zeichenmenge bei dem Gästebucheintrag begrenzen. Beispielsweise max. 200 Zeichen pro Eintrag. Das würde per Javascript gehen. Nur wenn sich der Client auskennt, kann er das ja umgehen und meinem Server z. B. den gesamten Bibeltext schicken - was der Server dann nicht mehr speichern könnte.

Die Methoden "get" und "post" sind mir bekannt.

Nun meine drei Fragen:

Gibt es eine Möglichkeit, serverseitig (Perl) die zu empfangenen Daten von vorne herein zu begrenzen? Also wenn das Formular mehr sendet als z. B. die erwähnten 200 Zeichen, die Übertragung zu beenden und eine Fehlermeldung auszugeben? (Dann wäre der Manipulationsversuch gescheitert)

Kann man die IP des Gastes mit Uhrzeit speichern und erst nach Ablauf von einer Minute für einen weiteren Gästebucheintrag freigeben? (soll verhindern, das ein automatisches Programm in der Endlosschleife die Gästebuchdatei vollstopft.)

Wie groß ist die Gefahr wirklich, das bösartige Clients über die cgi versuchen, direkte Befehle an den Server zu geben, mit dem Ziel die Kontrolle über diesen zu erlangen. Ich habe gelesen, das dies möglich sein soll. Weis allerdings nicht mehr ob dies nur PHP-Scrips betraf oder auch für Perl galt.

Vielleicht kann ja der ein oder andere hier ewas dazu sagen

Danke - g-force

  1. Gibt es eine Möglichkeit, serverseitig (Perl) die zu empfangenen Daten von vorne herein zu begrenzen? Also wenn das Formular mehr sendet als z. B. die erwähnten 200 Zeichen, die Übertragung zu beenden und eine Fehlermeldung auszugeben? (Dann wäre der Manipulationsversuch gescheitert)

    my $maxlenth=1000;
    my $clean = '';
    $eviluserinput =~ /^(.{0,$maxlength})/ and $cleantext=$1;

    Kann man die IP des Gastes mit Uhrzeit speichern und erst nach Ablauf von einer Minute für einen weiteren Gästebucheintrag freigeben? (soll verhindern, das ein automatisches Programm in der Endlosschleife die Gästebuchdatei vollstopft.)

    man kann...

    Wie groß ist die Gefahr wirklich, das bösartige Clients über die cgi versuchen, direkte Befehle an den Server zu geben, mit dem Ziel die Kontrolle über diesen zu erlangen. Ich habe gelesen, das dies möglich sein soll. Weis allerdings nicht mehr ob dies nur PHP-Scrips betraf oder auch für Perl galt.

    Ich schenke dir eine Funktion, die du kontextgerecht anwenden sollst:

    sub htmlchars {  
       my $s = shift || '';  
       $s =~ s/\&/\&/go;  
       $s =~ s/</\&lt;/go;  
       $s =~ s/>/\&gt;/go;  
       $s =~ s/"/\&quot;/go;  
       return $s;  
    }  
    
    

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. Hi Beat

      Habe mir mal das:

      my $maxlenth=1000;
      my $clean = '';
      $eviluserinput =~ /^(.{0,$maxlength})/ and $cleantext=$1;

      und das:

      Ich schenke dir eine Funktion, die du kontextgerecht anwenden sollst:

      sub htmlchars {

      my $s = shift || '';
         $s =~ s/&/&amp;/go;
         $s =~ s/</&lt;/go;
         $s =~ s/>/&gt;/go;
         $s =~ s/"/&quot;/go;
         return $s;
      }

      
      >   
        
      ausgedruckt. Ich habe so das Gefühl, daß es wichtig ist :-)  
        
      Bevor ich jetzt gleich meine Nase in die Perlfibel stecke:  
      Der zweite Codeteil - Filtert der da böse Steuerzeichen heraus bzw. schreibt sie um? Sieht nämlich für mich als Perlneuling  und alter Basickenner so ähnlich aus.  
        
      Danke an euch beide für eure Antworten.  
        
      g-force
      
      1. sub htmlchars {

        my $s = shift || '';
           $s =~ s/&/&amp;/go;
           $s =~ s/</&lt;/go;
           $s =~ s/>/&gt;/go;
           $s =~ s/"/&quot;/go;
           return $s;
        }

          
        
        > Der zweite Codeteil - Filtert der  
          
        nein  
          
        
        > da böse  
          
        nein  
          
        
        > Steuerzeichen  
          
        nein  
          
        
        > heraus bzw. schreibt sie um?  
          
        schon eher-  
        Es maskiert Html-Spezialzeichen im HTML-Kontext und beugt damit XSS-Atacken vor.  
          
        mfg Beat
        
        -- 
        
        ><o(((°>           ><o(((°>  
        
           <°)))o><                     ><o(((°>o  
        Der Valigator leibt diese Fische
        
        1. Hi Beat

          schon eher-
          Es maskiert Html-Spezialzeichen im HTML-Kontext und beugt damit XSS-Atacken vor.

          Habe mich ein wenig eingelesen :-)

          Begriff masskieren ist jetzt klar. Das ist wie bei den HTML-Entities und dem "&nbsp" für ein Leerzeichen.

          XSS= Cross Site Scripting:
          Nach meinem Verständnis wird hier HTML-Code in die Ausgabe der nächsten Seitenausgabe über den Umweg der Gästebuchdatei eingebaut.

          Beispiel:
          Im HTML-Formula z. B. <script type="text/javascript">. Das wird via cgi zum Server geschickt. Dort wird es als vermeintliches Gästebucheintrag in der Datei guest.csv abgespeichert. Beim nächsten Aufruf des Gästebuches wird dann der Gästebucheintrag mit dem Javascript-Inhalt ausgelesen und dem Client angezeigt - ggf dort als Script ausgeführt.

          Wenn ich aber alle Zeichen, die der Client eingibt, genau so speichere (utf-8 Text), dann sollte doch auch der Scriptcode lediglich als Text ausgegeben werden, wenn dieser in Anführungszeichen steht und der Browserclient kommt gar nicht erst auf die Idee JS auszuführen. Oder liege ich da falsch?

          Nach dem was ich gelesen habe hat das XSS keinen Einfluß auf das Perlscript bzw. auf den Server?

          Es schadet, wenn überhaupt "nur" andere Busucher des Gästebuches (was natürlich auch nicht im Sinne des Erfinders liegt).

          g-force

          1. Wenn ich aber alle Zeichen, die der Client eingibt, genau so speichere (utf-8 Text), dann sollte doch auch der Scriptcode lediglich als Text ausgegeben werden, wenn dieser in Anführungszeichen steht und der Browserclient kommt gar nicht erst auf die Idee JS auszuführen. Oder liege ich da falsch?

            Die zeichenkodierung ist irrelevant, da HTML-Spezialzeichen eh alles ASCII Zeichen sind.
            Nein es geht darum, dass ein Autor kein gültiges HTML produzieren darf.
            Deshalb hast du die Zeichen <>"& im HTML Kontext zu maskieren.

            Es schadet, wenn überhaupt "nur" andere Busucher des Gästebuches (was natürlich auch nicht im Sinne des Erfinders liegt).

            Wenn du ein XML Speicherformat wählst, dann ist dein Speicherformat ein XML Kontext und du hast XML-gerecht zu maskieren.

            Verstehe das Prinzip Kontext.

            mfg Beat

            --
            ><o(((°>           ><o(((°>
               <°)))o><                     ><o(((°>o
            Der Valigator leibt diese Fische
  2. Hallo

    Um zu vermeiden, das "unendlich" viel Text übertragen wird, welcher ja Speicherplatz auf dem Server belegt, wollte ich die Zeichenmenge bei dem Gästebucheintrag begrenzen. Beispielsweise max. 200 Zeichen pro Eintrag. Das würde per Javascript gehen. Nur wenn sich der Client auskennt, kann er das ja umgehen und meinem Server z. B. den gesamten Bibeltext schicken - was der Server dann nicht mehr speichern könnte.

    Die Methoden "get" und "post" sind mir bekannt.

    Nun meine drei Fragen:

    Gibt es eine Möglichkeit, serverseitig (Perl) die zu empfangenen Daten von vorne herein zu begrenzen? Also wenn das Formular mehr sendet als z. B. die erwähnten 200 Zeichen, die Übertragung zu beenden und eine Fehlermeldung auszugeben? (Dann wäre der Manipulationsversuch gescheitert)

    Natürlich kannst du mit einer serverseitigen Sprache die Anzahl der Zeichen – hier die des Textfeldes – ermitteln und dann entscheiden, ob du den Eintrag verwirfst oder abschneidest bzw. in Gänze speicherst.

    Kann man die IP des Gastes mit Uhrzeit speichern und erst nach Ablauf von einer Minute für einen weiteren Gästebucheintrag freigeben? (soll verhindern, das ein automatisches Programm in der Endlosschleife die Gästebuchdatei vollstopft.)

    Ja, das kann man. Entweder du speicherst die Daten beim Eintrag oder in einer eigenen Datei, gegen die dann bei jedem Eintragsversuch geprüft wird. Die Daten sollten nach einer gewissen Zeit wieder bereinigt werden, sonst läuft dir die Prüfdatei auch irgendwann über.

    Wie groß ist die Gefahr wirklich, das bösartige Clients über die cgi versuchen, direkte Befehle an den Server zu geben, mit dem Ziel die Kontrolle über diesen zu erlangen. Ich habe gelesen, das dies möglich sein soll. Weis allerdings nicht mehr ob dies nur PHP-Scrips betraf oder auch für Perl galt.

    Von Misskonfigurationen des Servers abgesehen obliegt es dir bei der Verarbeitung der hereinkommenden Daten, diese zu prüfen und zu benutzen oder zu verwerfen.

    Tschö, Auge

    --
    Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war.
    Terry Pratchett, "Wachen! Wachen!"
    Veranstaltungsdatenbank Vdb 0.3
  3. hi,

    Um zu vermeiden, das "unendlich" viel Text übertragen wird, welcher ja Speicherplatz auf dem Server belegt, wollte ich die Zeichenmenge bei dem Gästebucheintrag begrenzen.

    Am Einfachsten mit substr() auf das Textfeld. Du solltest jedoch einen POST generell und unabhängig auf einen zweckmäßigen Wert beschränken, unabhängig von den Eingabefeldnamen, nutze dazu den header Content-Length.

    Kann man die IP des Gastes mit Uhrzeit speichern und erst nach Ablauf von einer Minute für einen weiteren Gästebucheintrag freigeben? (soll verhindern, das ein automatisches Programm in der Endlosschleife die Gästebuchdatei vollstopft.)

    Lass die IP aus dem Spiel.

    use Ticket;

    Wie groß ist die Gefahr wirklich, das bösartige Clients über die cgi versuchen, direkte Befehle an den Server zu geben, mit dem Ziel die Kontrolle über diesen zu erlangen. Ich habe gelesen, das dies möglich sein soll.

    Mit einer zweckmäßigen Kontrollstruktur über die Parameter hast _Du_ die Kontrolle über Dein Script, nicht der Client.

    Hotti

    1. Hallo hotti

      Nochmal kurz zur Verinnerlichung:

      Angenommen ich verwende get (oder post), dann wird der Gästebucheintrag im Formular (Textfeld) per cgi zum Server gesendet. Auf dem Server kann mit Query_String alles nach dem Fragezeichen (get-Methode) ausgelesen und in eine Variable gepackt werden. Hierbei kann ich mit substring bestimmen, daß beispielsweise nur 200 Zeichen in die neue Variable gepackt werden.

      Nehmen wir jetz aber mal an, daß ein "Evil"-User eine _sehr_ lange Zeichenkette abschickt. Welche Konsequenzen hat das auf den Server? Bricht der ab - oder eher zusammen? Was passiert mit der Variable Query_String in solch einem Fall? Und beim nächsten Aufruf durch einen weiteren Client? Muss ich da die Query_String löschen oder wird die bei jedem cgi-Aufruf automatisch zurückgesetzt?

      g-force

      1. hi,

        natürlich bricht auch ein Server zusammen, wenn viele zeitgleiche Requests erfolgen und große Datenmengen in den RAM gelesen werden müssen.

        QUERY_STRING / GET: Irgendwo gibt es eine Längenbegrenzung, da müsste ich erst suchen in den RFCs, das kannst aber auch Du ;-)

        Wenn QS geparst wird, wird der ersteinmal komplett in den RAM gelesen, dann die Komponenten. Es gibt also einen Moment, wo die Daten faktisch doppelt vorliegen, dazu kommt noch das Unescape, was CPU braucht.

        Interessanter wird es bei POST, hier generiert der Browser einen Header mit der Angabe Content-Length. An der Stelle könntest Du die Scriptverarbeitung abbrechen, wenn dieser Wert ein von Dir bestimmtes Limit erreicht hat. Zu dem Zeitpunkt, wo Content-Length bekannt ist, stehen die Daten noch an STDIN, sind also noch nicht geparst.

        Es gibt außer substr() noch andere Möglichkeiten zur Begrenzung, die sind jedoch byte-orientiert. substr() ist zeichenorientiert, interessant wird das Thema bei utf-8, wo also Zeichen mehr als 1 byte lang sind, hierzu hilft das Pragma utf8;

        no utf8;
        print length('€'); # 3

        use utf8;
        print length('€'); # 1

        Viel Spaß mit Perl,
        Horst Haselhuhn

        1. Es gibt außer substr() noch andere Möglichkeiten zur Begrenzung, die sind jedoch byte-orientiert. substr() ist zeichenorientiert, interessant wird das Thema bei utf-8, wo also Zeichen mehr als 1 byte lang sind, hierzu hilft das Pragma utf8;

          Das ist falsch, wenn die Daten von aussen kommen.

          http://perldoc.perl.org/utf8.html

          Do not use this pragma for anything else than telling Perl that your script is written in UTF-8. The utility functions described below are directly usable without use utf8; .

          Du kannst z.b. use encoding 'utf8'; verwenden um utf-8 Strings zu verarbeiten.

          http://perldoc.perl.org/encoding.html

          Struppi.

          1. Es gibt außer substr() noch andere Möglichkeiten zur Begrenzung, die sind jedoch byte-orientiert. substr() ist zeichenorientiert, interessant wird das Thema bei utf-8, wo also Zeichen mehr als 1 byte lang sind, hierzu hilft das Pragma utf8;

            Das ist falsch, wenn die Daten von aussen kommen.

            Na Struppi, soso, "von aussen"...(???), hast Du immer noch nicht gelernt, mit UTF-8-codierten Zeichen richtig umzugehen?

            Hotti

            1. Es gibt außer substr() noch andere Möglichkeiten zur Begrenzung, die sind jedoch byte-orientiert. substr() ist zeichenorientiert, interessant wird das Thema bei utf-8, wo also Zeichen mehr als 1 byte lang sind, hierzu hilft das Pragma utf8;

              Das ist falsch, wenn die Daten von aussen kommen.

              Na Struppi, soso, "von aussen"...(???), hast Du immer noch nicht gelernt, mit UTF-8-codierten Zeichen richtig umzugehen?

              Bitte? Les mal mit use utf8 utf-8 kodierte Textdateien ein.

              #!/usr/bin/perl -w  
                
              use strict;  
                
              # In utf.txt ist ein € in utf-8 kodiert  
              open FH, '<', 'utf.txt';  
              my $c = <FH>;  
              close FH;  
                
              no utf8;  
              print length($c); # 3  
                
              use utf8;  
                
              print length($c); # 3  
              
              

              Du siehst es hat keine Wirkung.

              Struppi.

        2. Es gibt außer substr() noch andere Möglichkeiten zur Begrenzung, die sind jedoch byte-orientiert. substr() ist zeichenorientiert, interessant wird das Thema bei utf-8, wo also Zeichen mehr als 1 byte lang sind, hierzu hilft das Pragma utf8;

          no utf8;
          print length('€'); # 3

          use utf8;
          print length('€'); # 1

          Es kann sein, dass ich "noch nicht gelernt habe mit utf-8 kodierten Zeichen umzugehen". Aber du ebenso wenig.

          Das Pragma use utf8 wirkt, wie es auch in der Doku steht nur auf den Perl Quelltext, nicht auf das was von Aussen kommt.

          Aber das ganze scheint noch wesentlich vertrackter zu sein.

          Hier ein Skript, dessen Quellcode in utf-8 ist:
          http://jstruebig.de/cgi-bin/utf.pl

          Wie du siehst, wird die Länge des Input (also das was von aussen kommt) in keinem Fall richtig berechnet.

          Merkwürdig, ist dass das 'ä' mit use utf8 als ISO Zeichen ausgegeben wird.

          Jetzt das gleich Skript, in dem ich die 'ä' durch ein '€' Zeichen ausgetauscht habe, sonst hat sich nichts geändert.
          http://jstruebig.de/cgi-bin/utf_mit_euro.pl

          Auch hier wieder, keine Länge wird richtig berechnet und mit use utf8 wird der Input so umgewandelt, dass er nicht mehr in der HTML Seite dargestellt wird.

          Wie auch immer, dein Rat use utf8 zu verwenden, ist mit großer Vorsicht zu geniessen, da er zu falschen Ausgaben führt. Es steht ja auch in der Doku use utf8 ist lediglich dazu da, dass Perl sagst, dass der Quellcode in utf8 vorliegt. Du scheinst diese Aussage ignorieren zu wollen.

          Struppi.

          1. Hi!

            Es kann sein, dass ich "noch nicht gelernt habe mit utf-8 kodierten Zeichen umzugehen". Aber du ebenso wenig.
            Das Pragma use utf8 wirkt, wie es auch in der Doku steht nur auf den Perl Quelltext, nicht auf das was von Aussen kommt.

            Gibt es vielleicht Unterschiede, ob ein Pragma global gesetzt wird oder beim Initialisieren vom CGI-Modul?
            http://perldoc.perl.org/CGI.html#-utf8

            Lo!

            1. Das Pragma use utf8 wirkt, wie es auch in der Doku steht nur auf den Perl Quelltext, nicht auf das was von Aussen kommt.

              Gibt es vielleicht Unterschiede, ob ein Pragma global gesetzt wird oder beim Initialisieren vom CGI-Modul?
              http://perldoc.perl.org/CGI.html#-utf8

              Den Schalter hatte ich auch verwendet, der ändert aber hier gar nichts.

              Struppi.

              1. Hi!

                http://perldoc.perl.org/CGI.html#-utf8
                Den Schalter hatte ich auch verwendet, der ändert aber hier gar nichts.

                Und wenn du, wie dort empfohlen, die Dekodierung selbst vornimmst?

                Lo!

                1. http://perldoc.perl.org/CGI.html#-utf8
                  Den Schalter hatte ich auch verwendet, der ändert aber hier gar nichts.

                  Und wenn du, wie dort empfohlen, die Dekodierung selbst vornimmst?

                  Auch nicht. Der String wird immer in Bytelänge gemessen, er muss erst auf die interne Kodierung mit decode umgewandelt werden, was aber bei dem Eurozeichen mißlingt.

                  Mir ist das aber jetzt zu müßig, rauszufinden wie es am sinnvollsten ist. Mir ging es um die von Rolf wiederholt gebrachte Aussage, dass man use utf8 verwenden könnte. Was aber zu mehr Problemen führt, als das es eine Lösung ist.

                  Struppi.