Gustl: timelocal - scriptabbruch bie falscher datumseingabe verhindern

Hallo Leute !

timelocal bricht natürlich das script ab, wenn man ein falsches datum übergibt, z.b: den 30 . 02 . oder gar den 65 . 13 .

wie kann ich den abbruch des scripts verhindern und eine vernünftig formatierte fehlermeldung mit eigenem print in den browser drucken ? mit software-error allein kann ein user ja nichts anfangen.

$unix=timelocal(59,59,23,$day,$month,$year);

--
Theorie: Alles ist möglich - Praxis: Nix funzt - Ich bin eben ein Mann der Praxis

--
G. DAVID
  1. wie kann ich den abbruch des scripts verhindern und eine vernünftig formatierte fehlermeldung mit eigenem print in den browser drucken ? mit software-error allein kann ein user ja nichts anfangen.

    Ein blick in die Doku hilft meistens:
    http://cpan.uwinnipeg.ca/htdocs/Time-Local/Time/Local.html

    The timelocal() and timegm() functions perform range checking on the input $sec, $min, $hour, $mday, and $mon values by default.

    If you are working with data you know to be valid, you can speed your code up by using the ``nocheck'' variants, timelocal_nocheck() and timegm_nocheck(). These variants must be explicitly imported.

    Struppi.

    --
    Javascript ist toll (Perl auch!)
    1. Guten Morgen. Es ist jetzt 00:20:23:44:17 UTC

      wie kann ich den abbruch des scripts verhindern und eine vernünftig formatierte fehlermeldung mit eigenem print in den browser drucken ? mit software-error allein kann ein user ja nichts anfangen.

      Ein blick in die Doku hilft meistens:
      http://cpan.uwinnipeg.ca/htdocs/Time-Local/Time/Local.html

      The timelocal() and timegm() functions perform range checking on the input $sec, $min, $hour, $mday, and $mon values by default.

      If you are working with data you know to be valid, you can speed your code up by using the ``nocheck'' variants, timelocal_nocheck() and timegm_nocheck(). These variants must be explicitly imported.

      Struppi.

      Hi Struppi servus :) Ja, nocheck lässt das script einfach durchlaufen, aber ich brauch ne fehlermeldung. ich kann ja nicht jedes schaltjahr einzeln abfragen ... in der cpan find ich keinen rückgabewert ...

      --
      Theorie: Alles ist möglich - Praxis: Nix funzt - Ich bin eben ein Mann der Praxis

      --
      G. DAVID
  2. Hallo.

    wie kann ich den abbruch des scripts verhindern und eine vernünftig formatierte fehlermeldung mit eigenem print in den browser drucken ? mit software-error allein kann ein user ja nichts anfangen.

    Du könntest den Fehler mit eval abfangen und anschließend die Variable $@ abfragen:

    #!perl -w  
      
    use strict;  
    use Time::Local;  
      
    my $year = 107;  
    my $month = 13;  
    my $day = 65;  
      
    my $unix = eval { timelocal(59, 59, 23, $day, $month, $year) };  
      
    if($@) {  
      print "Something went wrong: $@";  
     }  
    else {  
      print "Everything is fine.";  
     }
    

    Das sollte den erwünschten Effekt bringen.

    Schöne Grüße.

    1. Guten Morgen. Es ist jetzt 00:20:23:44:17 UTC

      Hallo.

      wie kann ich den abbruch des scripts verhindern und eine vernünftig formatierte fehlermeldung mit eigenem print in den browser drucken ? mit software-error allein kann ein user ja nichts anfangen.

      Du könntest den Fehler mit eval abfangen und anschließend die Variable $@ abfragen:

      #!perl -w

      use strict;
      use Time::Local;

      my $year = 107;
      my $month = 13;
      my $day = 65;

      my $unix = eval { timelocal(59, 59, 23, $day, $month, $year) };

      if($@) {
        print "Something went wrong: $@";
      }
      else {
        print "Everything is fine.";
      }

      
      >   
      > Das sollte den erwünschten Effekt bringen.  
      >   
      > Schöne Grüße.  
        
      Ohhh, so einfach ? Ja genau danach hab ich gesucht ! Hab gestern zwar vor meinem Posting hier eval überflogen, war aber wohl zu müde ums zu verstehen. Allerdings steht bei eval in selfhtml:  
        
      Scripts wie im Beispiel oben können extrem gefährlich sein. Benutzen Sie so etwas niemals als öffentlich zugängliches CGI-Script! Denn der übergebene Code, den das Script vom Anwender erhält, wird gnadenlos ausgeführt. Wenn der Anwender jemand ist, der sich auskennt, kann er statt der geforderten Rechenoperation beispielsweise einen Aufruf von system übergeben, bei dem ein ganzer Verzeichnisbaum gelöscht oder die Festplatte formatiert wird...  
        
      Ja das wird schon mal öffentlich zugänglich. Was kann ich da tun ? Bzw. trifft das überhaupt auf mich zu ? Die Variablen tag, monat, jahr die ich an eval (timelocal ...) übergebe hab ich vorher schon bereinigt, z.B: dürfens nur zahlen sein und ich filtere alle leerzeichen raus. Meine Kenntnisse gehen da nicht so tief, aber nach meinem Verständnis kann ein User dann einen derartigen Aufruf nur über die 3 Variablen schicken, und ein Sytemaufruf dieser Art kann nicht mur aus Zahlen bestehen. Lieg ich da richtig ?  
        
      Grüssle Gustl  
        
      
      
      1. Hallo.

        Allerdings steht bei eval in selfhtml:

        Scripts wie im Beispiel oben können extrem gefährlich sein. Benutzen Sie so etwas niemals als öffentlich zugängliches CGI-Script! [...]

        Das erste Beispiel zu eval in SELFHTML sollte man tatsächlich nicht verwenden. Aber dort wird eval auch nicht zum Abfangen von Fehlern genutzt, stattdessen wird eine Zeichenkette übergeben, die dann zur Laufzeit geparst und ausgeführt wird. Das ist sehr unsicher, zumal im Beispiel keine Prüfung der vom Benutzer übergebenen Werte erfolgt.

        Ja das wird schon mal öffentlich zugänglich. Was kann ich da tun ? Bzw. trifft das überhaupt auf mich zu ? Die Variablen tag, monat, jahr die ich an eval (timelocal ...) übergebe hab ich vorher schon bereinigt, z.B: dürfens nur zahlen sein und ich filtere alle leerzeichen raus. Meine Kenntnisse gehen da nicht so tief, aber nach meinem Verständnis kann ein User dann einen derartigen Aufruf nur über die 3 Variablen schicken, und ein Sytemaufruf dieser Art kann nicht mur aus Zahlen bestehen. Lieg ich da richtig ?

        Wenn du eval mit einem Anweisungs-Block aufrufst, ist es wesentlich sicherer, als die Zeichenketten-Variante. Die Befehle im Block sind in diesem Fall bereits zur Kompilierzeit bekannt. Zur Laufzeit können dann keine weiteren Befehle eingeschleust werden, weil der Code ja bereits feststeht.

        Hier ist ein kleines Beispiel zur Erklärung:

        #!perl -w  
          
        use strict;  
        use Time::Local;  
          
        # Datumswerte mit vom Benutzer manipulierter Jahreszahl  
        my $year = '0); BEGIN { print "[Bösartiger Code]\n" }; (';  
        my $month = 13;  
        my $day = 65;  
        my $unix;  
          
        # eval BLOCK: Warnung, weil $year nicht numerisch ist  
        #             Bösartiger Code wird NICHT ausgeführt  
        #             eval-Fehler wegen falscher Datumswerte  
        print "eval BLOCK:\n";  
        $unix  = eval { timelocal(59, 59, 23, $day, $month, $year) };  
        print "eval-Fehler: $@\n" if($@);  
          
        # eval EXPR: Bösartiger Code wird ausgeführt  
        #            eval-Fehler wegen falscher Datumswerte  
        print "eval EXPR:\n";  
        $unix = eval("timelocal(59, 59, 23, $day, $month, $year)");  
        print "eval-Fehler: $@\n" if($@);
        

        Im obigen Beispiel gehen wir davon aus, dass der Benutzer die Datumsangaben gemacht hat. Der Benutzer hat an der Stelle das Wissen darüber, dass die Funktion timelocal() verwendet wird und hat die Jahreszahl entsprechend manipuliert, um seinen bösartigen Code einzuschleusen.

        Im ersten Fall wird eval mit einem Block aufgerufen, um von timelocal() erzeugte Fehler abzufangen. Der bösartige Code würde an dieser Stelle lediglich eine Warnung erzeugen, da er nicht numerisch ist, timelocal() jedoch versucht, damit zu rechnen. Eine Gefahr besteht hier nicht, da der Code nicht ausgeführt wird, sondern nur als Text an timelocal() weitergegeben wird. Vorallem, wenn du vorher geprüft hast, ob der Wert ausschließlich Ziffern enthält (/^\d+$/), kann hier nichts schief gehen.

        Im zweiten Fall wird eval eine Zeichenkette übergeben. Die Zeichenkette wird zur Laufzeit (sobald die Werte der Variablen bekannt sind) zusammengesetzt, geparst und anschließend ausgeführt - und das erfolgt tatsächlich gnadenlos, so wie es im SELFHTML-Beispiel steht. Im obigen Fall würde dann der folgende Code ausgeführt:

        timelocal(59, 59, 23, 65, 13, 0);  
        BEGIN { print "[Bösartiger Code]\n" };  
        ()
        

        Und anstatt der simplen print-Anweisung könnten an dieser Stelle Daten geändert, gelöscht oder eben System-Aufrufe abgesetzt werden.

        eval ist also gefährlich, wenn man ihm eine Zeichenkette übergibt, die vor ihrem Zusammenbau nicht ausreichend auf fehlerhafte/manipulierte Werte geprüft wurde. Bei der Verwendung von eval zum Abfangen von Fehlern, sehe ich kein Sicherheitsrisiko.

        Schöne Grüße.

        1. Hallo.

          Allerdings steht bei eval in selfhtml:

          Scripts wie im Beispiel oben können extrem gefährlich sein. Benutzen Sie so etwas niemals als öffentlich zugängliches CGI-Script! [...]

          Das erste Beispiel zu eval in SELFHTML sollte man tatsächlich nicht verwenden. Aber dort wird eval auch nicht zum Abfangen von Fehlern genutzt, stattdessen wird eine Zeichenkette übergeben, die dann zur Laufzeit geparst und ausgeführt wird. Das ist sehr unsicher, zumal im Beispiel keine Prüfung der vom Benutzer übergebenen Werte erfolgt.

          Ja das wird schon mal öffentlich zugänglich. Was kann ich da tun ? Bzw. trifft das überhaupt auf mich zu ? Die Variablen tag, monat, jahr die ich an eval (timelocal ...) übergebe hab ich vorher schon bereinigt, z.B: dürfens nur zahlen sein und ich filtere alle leerzeichen raus. Meine Kenntnisse gehen da nicht so tief, aber nach meinem Verständnis kann ein User dann einen derartigen Aufruf nur über die 3 Variablen schicken, und ein Sytemaufruf dieser Art kann nicht mur aus Zahlen bestehen. Lieg ich da richtig ?

          Wenn du eval mit einem Anweisungs-Block aufrufst, ist es wesentlich sicherer, als die Zeichenketten-Variante. Die Befehle im Block sind in diesem Fall bereits zur Kompilierzeit bekannt. Zur Laufzeit können dann keine weiteren Befehle eingeschleust werden, weil der Code ja bereits feststeht.

          Hier ist ein kleines Beispiel zur Erklärung:

          #!perl -w

          use strict;
          use Time::Local;

          Datumswerte mit vom Benutzer manipulierter Jahreszahl

          my $year = '0); BEGIN { print "[Bösartiger Code]\n" }; (';
          my $month = 13;
          my $day = 65;
          my $unix;

          eval BLOCK: Warnung, weil $year nicht numerisch ist

          #             Bösartiger Code wird NICHT ausgeführt
          #             eval-Fehler wegen falscher Datumswerte
          print "eval BLOCK:\n";
          $unix  = eval { timelocal(59, 59, 23, $day, $month, $year) };
          print "eval-Fehler: $@\n" if($@);

          eval EXPR: Bösartiger Code wird ausgeführt

          #            eval-Fehler wegen falscher Datumswerte
          print "eval EXPR:\n";
          $unix = eval("timelocal(59, 59, 23, $day, $month, $year)");
          print "eval-Fehler: $@\n" if($@);

          
          >   
          > Im obigen Beispiel gehen wir davon aus, dass der Benutzer die Datumsangaben gemacht hat. Der Benutzer hat an der Stelle das Wissen darüber, dass die Funktion timelocal() verwendet wird und hat die Jahreszahl entsprechend manipuliert, um seinen bösartigen Code einzuschleusen.  
          >   
          > Im ersten Fall wird eval mit einem Block aufgerufen, um von timelocal() erzeugte Fehler abzufangen. Der bösartige Code würde an dieser Stelle lediglich eine Warnung erzeugen, da er nicht numerisch ist, timelocal() jedoch versucht, damit zu rechnen. Eine Gefahr besteht hier nicht, da der Code nicht ausgeführt wird, sondern nur als Text an timelocal() weitergegeben wird. Vorallem, wenn du vorher geprüft hast, ob der Wert ausschließlich Ziffern enthält (/^\d+$/), kann hier nichts schief gehen.  
            
          `if ($input=~/\D/) {printfehler und goto end;}`{:.language-perl} hab ich so gemacht. hab das hoffentlich richtig verstanden? \D ... andere werte als zahlen enthält ...  
          
          >   
          > Im zweiten Fall wird eval eine Zeichenkette übergeben. Die Zeichenkette wird zur Laufzeit (sobald die Werte der Variablen bekannt sind) zusammengesetzt, geparst und anschließend ausgeführt - und das erfolgt tatsächlich gnadenlos, so wie es im SELFHTML-Beispiel steht. Im obigen Fall würde dann der folgende Code ausgeführt:  
          >   
          > ~~~perl
          
          timelocal(59, 59, 23, 65, 13, 0);  
          
          > BEGIN { print "[Bösartiger Code]\n" };  
          > ()
          
          

          Und anstatt der simplen print-Anweisung könnten an dieser Stelle Daten geändert, gelöscht oder eben System-Aufrufe abgesetzt werden.

          eval ist also gefährlich, wenn man ihm eine Zeichenkette übergibt, die vor ihrem Zusammenbau nicht ausreichend auf fehlerhafte/manipulierte Werte geprüft wurde. Bei der Verwendung von eval zum Abfangen von Fehlern, sehe ich kein Sicherheitsrisiko.

          Schöne Grüße.

          Dank Dir für dieses SUPER Beispiel ! Hast Dir echt Arbeit gemacht. Und ich kann beruhigt schlafen :)

          Schöne Grüsse Gustl