Thread Problem mit File Upload (29 answers)
Opened by Gast at 2007-12-06 12:20

morph
 2007-12-07 00:50
#103535 #103535
User since
2007-12-06
79 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hi Mathi.

Biite immer daran denken: Die meisten Angriffe kommen aus dem eigegen Netzwerk. Soll heißen, dass auch authorisierte Benutzer böse Menschen sein können, die ihren Schabernack treiben wollen.

Gast+2007-12-06 11:20:58--
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
use strict;
use warnings;
use CGI::Carp qw/fatalsToBrowser/;
use CGI qw/:cgi/;

# Schon hier oben muss CGI instanziert werden, weil es automatisch auch den
# QureyString zerlegt. Siehe weiter unten.

my $SID = "PHPSESSID"; # Hier dann Eintragen was die PHP Anwendnung verwendet.
my $cgi = new CGI;

## Get Unique ID Passed from PHP

# Also erst mal Directory Traversal Attacks abchecken !!!
# Und natürlich auch im Dateinamen, weil ein Angreifer das in seinem
# Tool dort geschickt einbaut.

exit if (
   $cgi->param($SID)       =~ |/\.\./| or
   $cgi->param('filename') =~ |/\.\./| 
);

# Und aussteigen wenn das einer versucht, denn dann braucht Dein
# Skript überhaupt nichts mehr machen. Solche Sachen am besten
# gleich zu Anfang des Skriptes, noch vor den Variablen Insitialisierung.


# Und den split hier kann man sich dann sparen, weil der die RegEx Engine 
# jetzt nochmal anwirft.
# my $sid = (split(/[&=]/,$ENV{QUERY_STRING}))[1];
$cgi->param($SID) =~ s/[^a-zA-Z0-9]//g;   

## Define Directory Paths (Must be Absolute Paths)
        
# Stings nur dann contantenieren, wenn es sich überhaupt nicht vermeiden
# lässt. Evaluieren muss Perl diese sowieso.
my $upload_dir  = "$ENV{DOCUMENT_ROOT}/upload_fraeszentrum/"; 
my $tmp_dir     = "$ENV{DOCUMENT_ROOT}/cgi-bin/tmp/";
my $session_dir = $tmp_dir.$cgi->($SID);

# Und das tmp würde ich im cgi-bin Verzeichnis anlegen, weil man daraus keine
# statischen Inhalte abrufen kann. So kann da keiner einfach mal reinschnuppern.
# Einer der Gründe warum ich CGI/Perl so liebe. Man braucht sich da keinen Kopf 
# um .htaccess und so 'ne Sachen machen :D


Und dann der eigentliche Upload.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
################################################################################ 
## Process Uploaded File
################################################################################
        if(-d $session_dir){ 
                # Das hatten wir oben schon.
                # my $query = new CGI;
                my $file_name = $cgi->param("filename");
                $file_name =~ s/.*[:\/\\](.*)/$1/; # Den Doppelpunkt für die Macs

                my $upload_file_path = $upload_dir.$file_name;
                my $upload_filehandle = $cgi->upload("filename");
                my $tmp_filename = "upl_".$$.$file_name; # TemporärDatei mit der PID
                # close($upload_filehandle);

                use Fcntl qw/:flock/;
                # Fcntl auf flock begrenzen, das spart speicher, weil das eine
                # ausgewachsene Bibliothek ist, die wir nicht in voller Größe
                # brauchen.

                # Maximum Uploadgröße 2MB (oder bei bedarf mehr).
                $CGI::POST_MAX = 1024 * 2048;

                open F, ">", $tmp_filename || &err_msg ( $upl_err."<br>$!" ); # Mein ErrorHandler
                flock F, LOCK_EX; # Datei sperren.
                binmode $tmp_filename; # Zur Sicherheit in den Binärmodus schalten.
                binmode F;
                while ( read $tmp_filename, my $buf, 1024 ) { print F $buf; }
                flock F, LOCK_UN; # Datei wieder freigeben.
                close F;

                # Und ganz wichtig: Den Inhalt der hochgeladenen Datei abprüfen.
                # Entsprechend den Vorgaben, was da hochgeladen werden darf.
                unless ( &chk_filecontent($tmp_filename) ) { exit; }
                else { 
                        use File::Copy;
                        print "Moving File to Upload Directory -> ";
                        if ( move ( $tmp_filename, $upload_file_path ) ) {
                                print "<b style='color:green;'>Success</b><br>"; 
                        }
                        else {
                                print "<font color='red'>Failure</font><br>";
                        }
                } # End unless chk_filecontent
        } # End if -d session_dir

sub chk_fileconent {
    $file = shift || return;
    # Hier jetzt Pseudocode!!!
    return ($file eq "OK") ? 1 : 0;
}


Abschließend:
Man kann zwar Dateien auch mit rename Verschieben, aber es ist nicht wirklich dafür geeignet. Man sollte damit lediglich Dateien umbenennen.
Das Modul CPAN:File::Copy verwendet die tatsächlich zu Grunde liegenden Betriebssystemfunktionmen.

Hoffe ich konnte ein wenig Licht ins Dunkle bringen.

-uw

EDIT:
Habe mir das Skript mal gezogen und angeschaut. Also das gehört in der Tat überarbeitet. ;)

Vielleicht liegt's auch an der Shebang-Teile. Check mal Dienen Webspace, bzw. Server, wo der Perlinterpreter steckt.

-uw

View full thread Problem mit File Upload