![]() |
Christian Kruse:
|
|
| |
| E-Mail: | |
|---|---|
| Homepage-URL: |
Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!
Wer kennt das Problem nicht: eine Datei soll über ein Formular und per
HTTP auf einen Server geladen werden, da ein FTP-Zugang nicht zur
Verfügung steht oder nicht eingesetzt werden darf/soll.
Dieser Artikel beschäftigt sich mit genau dieser Problematik und mit
den damit verbundenen Sicherheitslücken.
Für die Inbetriebnahme dieses Scripts benötigen Sie einen lauffähigen Webserver (siehe:
Webserver) mit CGI-Unterstützung (siehe:
CGI) und
Perl 5. Außerdem muss das Perl-Modul
CGI.pm installiert sein - dieses Modul gehört allerdings zur Standard-Distribution und sollte schon installiert sein.
Der folgende Perl-Quellcode enthält ein Beispiel für ein
Fileupload-Script.
#!/usr/bin/perl -w
use strict;
use CGI; # Modul fuer CGI-Programme
my $cgi = new CGI; # neues Objekt erstellen
# Content-type fuer die Ausgabe
print $cgi->header(-type => 'text/html');
# die datei-daten holen
my $file = $cgi->param("myfile");
# dateinamen erstellen und die datei auf dem server speichern
my $fname = 'file_'.$$.'_'.$ENV{REMOTE_ADDR}.'_'.time;
open DAT,'>'.$fname or die 'Error processing file: ',$!;
# Dateien in den Binaer-Modus schalten
binmode $file;
binmode DAT;
my $data;
while(read $file,$data,1024) {
print DAT $data;
}
close DAT;
print <<"HTML";
<html>
<head>
<title>Fileupload</title>
</head>
<body bgcolor="#FFFFFF">
<h1>Die Datei $file wurde erfolgreich hochgeladen.</h1>
<p>
Die Datei $file wurde erfolgreich auf dem Server
gespeichert.
</p>
</body>
</html>
HTML
Das Script bindet zunächst das Modul CGI.pm ein, das
für die Auswertung der übertragenen Daten sorgt.
Mit dem Befehl my $cgi = new CGI; wird ein neues
Objekt $cgi erstellt und die übergebenen Daten
werden eingelesen.
Die Methode CGI::param stellt dem Script sowohl ein Filehandle, als auch den Dateinamen
der hochgeladenen Datei zur Verfügung.
In der oberen While-Schleife wird die Datei in 1024-Byte-Blöcken eingelesen und in die
andere Datei geschrieben. Beide sind im Binär-Modus geöffnet, weil nicht bekannt
ist, ob die Daten, die ankommen, Binär- oder Text-Daten sind.
Zuletzt wird noch eine Bestätigung an den User weitergegeben, daß die Datei erfolgreich
gesichert wurde.
Dieses Script ist nicht für den praktischen Gebrauch gedacht, es dient lediglich als Beispiel. Bei einem für die Praxis gemachtem Script müssten die Sicherheits-Vorkehrungen viel strenger sein.
Alles nötige, um dieses Script in Betrieb zu nehmen, können sie in SELFHTML unter
CGI
und im Artikel
Die Inbetriebnahme eines CGI-Skripts von Michael Schröpl nachlesen.
Nun können Sie das Skript nutzen. Die Einbindung in Ihre HTML-Datei könnte z. B. so aussehen:
<form action="http://www.ihreadresse.de/cgi-bin/ihrscript.pl" method="post" enctype="multipart/form-data"> <input type="file" name="myfile" accept="text/*" maxlength="2097152"> <!-- hier beliebige andere Felder --> <input type="submit"><input type="reset"> </form>
Beim action-Attribut des <form>-Tags geben Sie
die URL-Adresse Ihres Fileupload-Scripts an. Über das Datei-Feld mit dem
Namen "myfile" wird die Datei an das Script übertragen.
Im Folgenden können Sie noch beliebig viele andere Formular-Felder
definieren.
Bitte geben Sie bei dem Datei-Feld immer den accept-Parameter und den
maxlength-Parameter an!
Diese sorgen dafür, daß nur bestimmte Dateien von bestimmter
Größe hochgeladen werden können. Allerdings wird beides bisher von keinem
bekannten Browser unterstützt, so daß sie auf jedenfall zusätzlich eine
Server-basierte Überprüfung machen sollten.
Ein Datei-Upload auf den Server bedeutet immer ein Sicherheits-Risiko. Ein Hacker könnte Ihr Script ausnutzen und eigene Scripts hochladen, so daß er Zugriff auf den Server und Ihre Dateien bekommt.
Deshalb sollten von Anfang an einige Sicherheits-Vorkehrungen getroffen werden. Dazu zählen unter anderem:
Das könnte z. B. so aussehen:
my @extensions = qw(txt dat gif jpg);
if($file{"filename"} !~ /^[a-z\.\-_]+?\.([a-z]{3})$/)
{ die("Ungültiger Dateiname"); }
else
{
my $extension = $1;
if(!grep($extension,@extensions))
{ die("Ungültige Dateiendung"); }
}
In dem obigen Code-Schnipsel wird ein Array @extensions mit gültigen Datei-Endungen
definiert.
Dann wird der Dateiname auf Integrität überprüft. Wenn
Sonderzeichen, shell pipes oder ähnliches darin
vorkommen, so wird das Script mit einer Fehlermeldung beendet.
Weitere Hinweise zu Sicherheit in CGI-Scripten lesen sie bitte im Artikel
CGI-Sicherheit von Wolfgang Wiese nach.