dchau has asked for the wisdom of the Perl Monks concerning the following question:

Can anyone help me make uploading files from a webform more secure? I know i have to watch for backticks, ., .., and such.............is there a simple regex that covers all this? I recall seeing one before but I can't seem to find it........thanks
#!/usr/bin/perl -w $| = 1; use CGI qw(param); use strict; my $file = param("file"); my @file_name = split(/\\/,$file); my $file_name = pop(@file_name); my $max_file_size = 2000000; my $base_dir = "/home/ducc/"; my $out_file = $base_dir . $file_name; my $log_file = $base_dir . "upload.log"; my ($total_bytes_read, $ip_log, $time_log); print "Content-type: text/html\n\n"; open (OUT, ">$out_file") || die "Can't open: $!"; open (LOG, ">>$log_file"); while (my $bytes_read = read($file, my $buffer, 1024)){ $total_bytes_read += $bytes_read; $ip_log = $ENV{'REMOTE_ADDR'}; $time_log = scalar localtime; if ($bytes_read > $max_file_size){ print "ERROR: The file you tried to upload is will not be uplo +aded<br>"; print "Your file is: $bytes_read bytes<br>"; print "The max file size you can upload is $max_file_size byte +s<br>"; close (OUT); unlink ($out_file); print LOG "ERROR: $time_log: $ip_log tried to upload $out_file + that was $bytes_read bytes\n"; die "$time_log: $ip_log tried to upload a file > $max_file_siz +e"; }else{ print OUT "$buffer"; print LOG "$time_log: $ip_log uploaded $out_file that was $byt +es_read bytes\n"; } } close (OUT) || die "Can't close: $!"; close (LOG); print "Completed uploading $file_name: $total_bytes_read bytes<br>"; print "Done...";

Replies are listed 'Best First'.
Re: Help make upload from web secure
by robsv (Curate) on May 10, 2001 at 20:29 UTC
    Just a quick comment- when you're writing CGI programs, it's a really good idea to use the -T command-line switch to enable taint checking:
    #!/usr/bin/perl -Tw
    Searching for "taint" here on Perl Monks will yield some good information. In terms of a regex to do some checking for you, The Camel ("Programming Perl", third edition) offers many suggestions in Chapter 23 ("Security"). Here's an example from the book that checks that $string contains only "word" characters:
    if ($string =~ /^([-\@\w.]+)$/) { $string = $1; } else { die "Bad data in $string"; }


    - robsv
(Ovid - insecure upload) Re: Help make upload from web secure
by Ovid (Cardinal) on May 10, 2001 at 21:44 UTC
    As a general rule of thumb, I would not let users choose the filename of files they upload.
    my $file = param("file"); my @file_name = split(/\\/,$file); my $file_name = pop(@file_name);
    What happens if the filename is .htaccess? I'm not really up on my un*x type environments, but I imagine that this could cause you heartaches.

    Also, since your shebang line (#!/usr/bin/perl -w) suggests that you are on a un*x type system, shouldn't your slashes be the other way? Consider the following:

    my $file ='../../bin/ls|'; my @file_name = split(/\\/,$file); my $file_name = pop(@file_name); print $file_name;
    That prints "../../bin/ls|" as the filename. With the reverse directory traversal, this should allow them to back up to the /bin directory and with the trailing pipe, run commands on the server. Again, I'm am not as familiar with non-Windows environments, but this doesn't look terribly secure to me.

    Of course, you also want taint checking. Read perlsec for details. Plus, my online CGI course has a bit of information about security that you may find useful.

    If I have my CPU up my exhaust port, please let me know.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Help make upload from web secure
by Trimbach (Curate) on May 10, 2001 at 20:58 UTC
    As has been repeated many times by those wiser than I, when determining whether data is "safe" or appropriate for your database/process/input/output/whatever you shouldn't focus on what you don't want (back ticks, non-ASCII, non-numbers, whatever) but rather on what you DO want. It's easy to think of all the things that ARE acceptable... it's much harder to think of everything that ISN'T acceptable. Sure enough you're going to forget something. Heck, the technology could even change (UNICODE, for example). Make your programs filter by what is good not by what is bad.

    Gary Blackburn
    Trained Killer

Re: Help make upload from web secure
by stephen (Priest) on May 10, 2001 at 20:55 UTC
    I would suggest perlman:perlsec, which contains all that I could say on the topic and more.

    stephen

Re: Help make upload from web secure
by Hero Zzyzzx (Curate) on May 10, 2001 at 20:57 UTC

    Well, I'm not saying mine is perfect, but see my node here. It has the advantage of running as a subroutine, and I think the regex is pretty safe. . . It will run find under taint and strict