Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

CGI::Application and CGI security

by Anonymous Monk
on Jun 30, 2004 at 14:19 UTC ( [id://370767]=perlquestion: print w/replies, xml ) Need Help??

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

I regularly use the following as recommended by Ovid's excellent Web Programming Using Perl course:
$CGI::DISABLE_UPLOADS = 1; # Disable uploads $CGI::POST_MAX = $max_post; # Maximum number of bytes per post

Where is the best place to put these statements when using CGI::Application? Before you issue a my $cgi = $self->query(); statement? In the setup method? The top of the program under the "use" statements but before the subs are defined? Thanks.

Replies are listed 'Best First'.
Re: CGI::Application and CGI security
by Arunbear (Prior) on Jun 30, 2004 at 15:32 UTC
    You can overide CGI::Application's cgiapp_get_query() method like so:
    sub cgiapp_get_query { my $self = shift; # Include CGI.pm and related modules require CGI; $CGI::DISABLE_UPLOADS = 1; # Disable uploads # Set Maximum number of bytes per post $CGI::POST_MAX = 1024; # Get the query object my $q = CGI->new(); return $q; }
    :-)
Re: CGI::Application and CGI security
by derby (Abbot) on Jun 30, 2004 at 14:25 UTC
    CGI::Application uses CGI (by default, you can use something else if you desire). From the docs for CGI:
    You can use these variables in either of two ways. 1. On a script-by-script basis Set the variable at the top of the script, right after the "use" statement: use CGI qw/:standard/; use CGI::Carp 'fatalsToBrowser'; $CGI::POST_MAX=1024 * 100; # max 100K posts $CGI::DISABLE_UPLOADS = 1; # no uploads 2. Globally for all scripts Open up CGI.pm, find the definitions for $POST_MAX and $DISABLE_UPLOADS, and set them to the desired values. You'll find them towards the top of the file in a sub­ routine named initialize_globals().

    -derby

    Update Arunbear's response is more accurate. In my code, I can get away with setting the variables at the top of the script since other included modules are pulling in CGI.pm (via use). If my code was more robust (and I utilized the dynamic nature of CGI::Application), setting the vars at the top of the script would do no good at all (and would just be lost when the CGI::Application requires CGI.pm). So no more + votes for this node, ++ to Arunbear node below.

Re: CGI::Application and CGI security
by dragonchild (Archbishop) on Jun 30, 2004 at 14:51 UTC
    What have you tried? I personally would put them right after the 'use CGI::Application;' line, but I haven't tested that.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

      Mostly I've placed it immediately beneath the use statements. It seems the most logical place. Ovid says to use them before you create a new CGI object. I don't know when CGI::Application does this, though my guess is that C::A doesn't create a CGI object until a query is requested. I do know that if used too late, the statements can't provide the intended protection.
        I do know that if used too late, the statements can't provide the intended protection.

        So, create a test that sees if the protection is there, verify that the test works by not having those statements, then put them in various places until you see the desired results.

        A neat side-benefit is that if you incorporate that test into your test-suite, you have a good security-related test for future reference.

        ------
        We are the carpenters and bricklayers of the Information Age.

        Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

        I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: CGI::Application and CGI security
by Anonymous Monk on Jun 30, 2004 at 17:10 UTC
    After reading the replies, I decided to test the $CGI::POST_MAX values. This is supposed to prevent DoS attacks by limiting the size of POST data, but I can't tell that changing the value makes any difference. My question now is, what is the expected behaviour if $POST_MAX is exceeded and everything works as it should? For instance, the following code executes with no warnings or errors:

    display form

    #!/usr/local/bin/perl use strict; use warnings; use CGI; $CGI::DISABLE_UPLOADS = 1; # Disable uploads $CGI::POST_MAX = 0; # Maximum number of bytes per post my $cgi = CGI->new(); print $cgi->header(); print " <html> <body> <form method='post' action='posttest.pl'> Username <input type='text' name='uid' size='15' value=''> <br><br> Password <input type='password' name='passwd' size='10' value='' +> <br><br> <input type='hidden' name='rm' value='test'> <input type='submit' name='submit'> </form> </body> </html> ";

    parse form

    #!/usr/local/bin/perl use strict; use warnings; use CGI; $CGI::DISABLE_UPLOADS = 1; # Disable uploads $CGI::POST_MAX = 0; # Maximum number of bytes per post my $cgi = CGI->new(); my $uid = $cgi->param('uid'); my $passwd = $cgi->param('passwd'); my $rm = $cgi->param('rm'); print $cgi->header, $cgi->start_html; print "uid: '" . $cgi->param('uid') . "<br>"; print "passwd: '" . $cgi->param('passwd') . "<br>"; print "rm: '" . $cgi->param('rm') . "'";
      Interesting ... from the CGI docs:
      $CGI::POST_MAX If set to a non-negative integer, this variable puts a ceiling on the size of POSTings ... An attempt to send a POST larger than $POST_MAX bytes will cause param() to return an empty CGI parameter list. You can test for this event by checking cgi_error(),
      However looking at the CGI code ($CGI::VERSION=3.05;), I see the following check:

      METHOD: { # avoid unreasonably large postings if (($POST_MAX > 0) && ($content_length > $POST_MAX)) { # quietly read and discard the post my $buffer; my $max = $content_length; while ($max > 0 && (my $bytes = $MOD_PERL ? $self->r->read($buffer,$max < 10000 ? $max : 10000) : read(STDIN,$buffer,$max < 10000 ? $max : 10000) )) { $self->cgi_error("413 Request entity too large"); last METHOD; } }
      I think that would be a bug in CGI.pm (anyone want to tell Lincoln). It seems to me that the line should be
      if (($POST_MAX > -1 ) && ($content_length > $POST_MAX))
      but then again ... setting $CGI::POST_MAX to 0 is kinda silly in a real world context.

      -derby

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (5)
As of 2024-03-28 16:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found