Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Security issues for CGI file upload

by rob_au (Abbot)
on Jan 18, 2002 at 20:31 UTC ( [id://139851]=perlquestion: print w/replies, xml ) Need Help??

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

In a chatterbox discussion earlier this evening, Chrisf and myself were discussing potential security issues with CGI file upload scripts. After a bit of discussion involving the use of temporary files, the main points of which I have covered previously here, I put together the following block of code - Note that this code is not considered to be a complete example, but merely sufficient to highlight the elements of the CGI upload interface discussed.

#!/usr/bin/perl -Tw use CGI; use CGI::Carp qw/ fatalsToBrowser /; use Fcntl; use File::Basename; use POSIX; use strict; $CGI::POST_MAX = 1048576; # Maximal file upload size $CGI::DISABLE_UPLOADS = 0; my $config = { 'allowed_file_types' => [ 'png', 'gif', 'jpg' ], 'upload_fields' => [ 'image_file' ] }; my $cgi = CGI->new; foreach my $field ( @{ $config->{ 'upload_fields' } } ) { if ( defined $cgi->param( $field ) ) { my $fextension = ( fileparse( $cgi->param($field), '\..*' ) )[ +2]; if ( grep { lc( $_ ) eq lc( $fextension ) } @{ $config->{ 'all +owed_file_types' } } ) { my $fname; { local *FH; do { $fname = tmpnam(); } until sysopen ( FH, $fname, O_RDWR|O_CREAT|O_EXCL, 0 +666 ); my $buffer; while ( read( $cgi->param( $field ), $buffer, 1024 ) ) + { syswrite FH, $buffer, length( $buffer ); } close FH; } # continue on and do stuff with uploaded file - file res +ides in temporary directory with file name $fname } else { # bad file extension } } }

Now while any form of file system interaction via a CGI interface is going to come with a number of inherent security concerns, are there any other immediate concerns which should be addressed in a script similar to that above?

Any and all suggestions for the tightening and/or improvement of this code process, particularly from a security point of view, are welcomed.

 

perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Replies are listed 'Best First'.
Re: Security issues for CGI file upload
by Hero Zzyzzx (Curate) on Jan 18, 2002 at 22:38 UTC

    What happens when the filesize exceeds $CGI::POST_MAX ? Not being snide, I have a need in an app I've built to check this and was unsure of the best way to do it and report to a user if there's an error. I'm curious to see how other monks handle it.

    -Any sufficiently advanced technology is
    indistinguishable from doubletalk.

      From CGI ...

      If set to a non-negative integer, this variable puts a ceiling on the size of POSTings, in bytes. If CGI.pm detects a POST that is greater than the ceiling, it will immediately exit with an error message. This value will affect both ordinary POSTs and multipart POSTs, meaning that it limits the maximum size of file uploads as well. You should set this to a reasonably high value, such as 1 megabyte.

      You can change this behaviour with a dispatch to your own code by altering the init method. eg.

      METHOD: { . . # avoid unreasonably large postings if (($POST_MAX > 0) && ($content_length > $POST_MAX)) { $self->cgi_error("413 Request entity too large"); last METHOD; } . . }

      Personally myself, I am happy to let CGI to return the error message.

       

      Update

       

      I had an additional thought on this topic determining a way to handle an over-sized post with our own error handling code without having to mess about with CGI module code. The following is the result, taking some liberties with the CGI source:

      #!/usr/bin/perl -Tw use strict; BEGIN { my $POST_MAX = 1048576; my $content_length = defined $ENV{'CONTENT_LENGTH'} ? $ENV{'CONTEN +T_LENGTH'} : 0; if ( ($POST_MAX > 0) && ($content_length > $POST_MAX) ) { # 413 request entity too large error handling } } use CGI;
      perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://139851]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-04-19 02:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found