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

CGI upload limit

by Ryszard (Priest)
on Sep 14, 2002 at 10:04 UTC ( [id://197837]=perlquestion: print w/replies, xml ) Need Help??

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

I've got an application suite developed with CGI::Application and HTML::Template.

I've got a few applications that require the user to upload certain files, however I'd like have an upload limit per application.

I know about the $CGI_POSTMAX variable, but this must be set before the CGI object is created, which is way before any of the applications make an appearance.

My question: Do you think it would make better sence to instill an application wide upload limit, or is it better to create an upload limit per application? (and how is this done)

My initial thoughts were to impose an upload limit per application, however thinking thru' it a little, given the purpose of this limit is to prevent a DoS, is there any reson to implement a limit per application?

Replies are listed 'Best First'.
Re: CGI upload limit
by valdez (Monsignor) on Sep 14, 2002 at 11:19 UTC

    Nice question, Ryszard.

    I would subclass CGI::Application and reimplement the query method:

    sub query { my $self = shift; my ($query) = @_; # We're only allowed to set a new query object if one does not yet e +xist! unless (exists($self->{__QUERY_OBJ})) { my $new_query_obj; # If data is provided, set it! Otherwise, create a new one. if (defined($query) && $query->isa('CGI')) { $new_query_obj = $query; } else { $CGI::POST_MAX=1024 * 100; # max 100K posts $new_query_obj = CGI->new(); } $self->{__QUERY_OBJ} = $new_query_obj; } return $self->{__QUERY_OBJ}; }

    Beware, the code isn't tested. The new method could also use a parameter passed during start up:

    my $webapp = App->new( TMPL_PATH => 'App/', PARAMS => { 'max_upload_size' => 100 } );

    Then you could check this parameter and act accordingly inside your reimplemented method. Another solution could be creating a new CGI object (with POST_MAX set properly) and passing it to application init; C::A will recognize the object and use it; here is an excerpt from the man page:

    QUERY - This optional parameter allows you to specify an already-created CGI.pm query object. Under normal use, CGI::Application will instantiate its own CGI.pm query object. Under certain conditions, it might be useful to be able to use one which has already been created.

    Hope this helps. Ciao, Valerio

      That's not really a good way to do it. What happens when a new version of CGI::Application comes out that makes a change in query()? The code above will break. Instead, call the real query() to do the work using SUPER:

      package CGI::Application::POST_MAX; use base 'CGI::Application'; sub query { my $self = shift; if (not exists $self->{__POST_MAX_SET__}) { $CGI::POST_MAX=1024 * 100; # max 100K posts $self->{__POST_MAX_SET__} = 1; } return $self->SUPER::query(@_); } 1;

      Of course, this still isn't 100% future-proof since it will break if a future version of CGI::Application uses the hash key "__POST_MAX_SET__" but I'd consider that an acceptable risk.

      But is this even necessary? Can't you just put this at the top of your CGI::Application class:

      BEGIN { $CGI::POST_MAX = 1020 * 100; }

      -sam

Re: CGI upload limit
by hiseldl (Priest) on Sep 14, 2002 at 22:23 UTC
    One way that I have used before to run an application with different configurations, in your case, a different upload limit per application, is to create separate directories with your CGI application copied to each with a different configuration for each one. This eliminates the need to put in any extra "which configuration do I need" logic, and also gives you the flexibility to password protect some dirs without affecting others.

    For instance, members using your CGI application may have a larger upload limit than non-members, so creating a separate directory with a "members-only" configuration allows you to do that with minimal effort.

    --
    hiseldl
    "Act better than you feel"

Re: CGI upload limit
by richardX (Pilgrim) on Sep 15, 2002 at 10:33 UTC
    It is a good idea to limit uploads, but probably not at the application level, unless you have a compelling business rule. You do have to decide if you really want limits on the size of one upload, or the total size of uploads, and the location where the uploads will be stored. I am assuming that you are allowing anonymous uploading and that opens a whole different can of worms. This will require you to filter out potentially bad file names, destructive HTML, Perl, and Java code, and a whole bunch of other security problems. On the other hand, I would do this even with authenticated users, because a lot of sabotage comes from within an organization.

    I would recommend only allowing authenticated users to do uploading. Your first level of protection should be authentication. I would then recommend limiting the size of each upload and the total size per application or user. If you are using Apache servers, you can set some limits at the server level Apache Limits . But this limit is only for each individual file. Your Perl code can also limit the file size. In this example, the author creates temporary directories on the fly so that someone cannot guess the directory name and some how force an upload. I have seen this technique used a lot so I would recommend it if you are concerned about DoS attacks. Quick and Dirty Method . Here is another example, which uses a text file that could be the starting point for tracking the total size uploaded by application or user. User Tracking .

    On the Perl side of the uploading CGI, I would log all requests for uploading, including the IP address, authenticated name, file name, file size, and a success code. This audit trail is most useful for finding problems and detecting attacks.

    In closing, I would hope that you would not rely on a single point of failure to protect your uploads. A good blend of Operating System, Server, and Perl limits should give you a good three-layer umbrella.

    Richard

    There are three types of people in this world, those that can count and those that cannot. Anon

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2024-04-19 22:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found