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

If you've been working with for any length of time, you know that it allows uploads by default and does not have a maximum post size. Since it saves the uploads as a temp file, someone can simply upload enough data to fill up your hard drive to initiate a DOS attack. To prevent this, we're regularly warned to include the following two lines at the top of our CGI scripts:

$CGI::DISABLE_UPLOADS = 1; # Disable uploads $CGI::POST_MAX = 512 * 1024; # limit posts to 512K max

As long as those are their before you instantiate a CGI object (or before you access param and related CGI functions with the function oriented interface), you have pretty safely plugged this problem. However, most CGI scripts don't have these lines of code. Some suggest changing these settings directly in I dislike this for two reasons:

  1. If you upgrade, you might forget to make the change to the new version.
  2. You may break a lot of existing code (which may or may not be a good thing depending upon the security implications).

So, my thought was to write a CGI::Safe module that inherits from It will establish the defaults for those variables and require virtually no code changes. Further, no existing code would be affected. You can also override the defaults established by explicitly stating them in your code or passing them as named arguments to the CGI::Safe constructor. It would work like this:

use CGI::Safe; my $q = CGI::Safe->new( DISABLE_UPLOADS => 0 );

This would be equivalent to:

use CGI::Safe; $CGI::DISABLE_UPLOADS = 0; my $q = CGI::Safe->new;

Since you can also pass arguments to the CGI constructor, you would pass them like this:

my $q = CGI::Safe->new( data => $stuff );

Just a rough hack:

################################ package CGI::Safe; ################################ $VERSION = .1; use strict; use CGI; use vars qw/ @ISA /; @ISA = ( "CGI" ); INIT { # Establish some defaults $CGI::DISABLE_UPLOADS = 1; # Disable uploads $CGI::POST_MAX = 512 * 1024; # limit posts to 512K max } sub new { my ( $self, %args ) = @_; $CGI::DISABLE_UPLOADS = $args{ DISABLE_UPLOADS } if exists $args{ +DISABLE_UPLOADS }; $CGI::POST_MAX = $args{ POST_MAX } if exists $args{ +POST_MAX }; return ( exists $args{ data } ) ? CGI::new( $self, $args{ data } ) + : CGI::new( $self ); }

I'm wondering if anyone sees any problems with this approach or if anyone has any suggestions.


Vote for paco!

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

Replies are listed 'Best First'.
Re: Preventing DOS attacks with
by tadman (Prior) on Aug 10, 2001 at 01:33 UTC
    This should certainly be a part of the standard CGI distribution, because if it was, I'd see no reason to use CGI so blindly.

    Why CGI doesn't turn this stuff off by default is beyond me. I would figure that it would be better for a few people to be wondering "Why don't my uploads work?" instead of a whole bunch of people wondering "Where did all my drive space go?"

      Since Lincoln Stein has added these global variables in, he's clearly aware of DOS problems. He has these fairly well documented in his POD, so I also wonder why they're not set. My guess is that he realizes that there is a hole here but he's trying to maintain backwards compatibility.

      I understand that one or both of these variables have been removed in versions 3+, so I'm curious how this situation has been addressed. tachyon raised this issue in this post about a security problem with 3.01. Since these globals don't appear to be present, it seems that this code wouldn't work for the newer versions.


      Vote for paco!

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats. version 3 is fairly bizarre. CPAN was "kind" enough to install it for me, and everything went to pot quite quickly. It had a tendency to declare the parameters as a non-scalar type CGI::Object. I'm not sure this is going to be a drop in replacement if that approach is taken, so there is no better time to fix all these outstanding issues.