Gustl: timelocal - scriptabbruch bie falscher datumseingabe verhindern

Beitrag lesen

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