This section demonstrates how a malicious user can bring the service down or cause problems by submitting unexpectedly big data.

Imagine that you have a guestbook script/handler, which works fine. But you've forgotten about a small nuance: you don't check the size of the submitted message. A 10 MB core file copied and pasted into the HTML textarea entry box intended for a guest's message and submitted to the server will make the server grow by at least 10 MB. (Not to mention the horrible experience users will go through when trying to view the guest book, since the contents of the binary core file will be displayed.) If your server is short of memory, after a few more submissions like this one it will start swapping, and it may be on its way to crashing once all the swap memory is exhausted.

To prevent such a thing from happening, you could check the size of the submitted argument, like this:

my $r = shift;
my %args = $r->args;
my $message = exists $args{message} ? $args{message} : '';
die "the message is too big" 
    unless length $message > 8192; # 8KB

While this prevents your program from adding huge inputs into the guest book, the size of the process will grow anyway, since you have allowed the code to process the submitted form's data. The only way to really protect your server from accepting huge inputs is not to read data above some preset limit. However, you cannot safely rely on the Content-Length header, since that can easily be spoofed.

You don't have to worry about GET requests, since their data is submitted via the query string of the URI, which has a hard limit of about 8 KB.

Think about disabling file uploads if you don't use them. Remember that a user can always write an HTML form from scratch and submit it to your program for processing, which makes it easy to submit huge files. If you don't limit the size of the form input, even if your program rejects the faulty input, the data will be read in by the server and the process will grow as a result. Here is a simple example that will readily accept anything submitted by the form, including fields that you didn't create, which a malicious user may have added by mangling the original form:

use CGI;
my $q = CGI->new;
my %args = map {$_ => $q->param($_)} $q->params;

If you are using CGI.pm, you can set the maximum allowed POSTsize and disable file uploads using the following setting:

use CGI;
$CGI::POST_MAX = 1048576;  # max 1MB allowed
$CGI::DISABLE_UPLOADS = 1; # disable file uploads

The above setting will reject all submitted forms whose total size exceeds 1 MB. Only non-file upload inputs will be processed.

If you are using the Apache::Request module, you can disable file uploads and limit the maximum POSTsize by passing the appropriate arguments to the new( ) function. The following example has the same effect as the CGI.pm example shown above:

my $apr = Apache::Request->new($r, 
                               POST_MAX        => 1048576,
                               DISABLE_UPLOADS => 1
                              );

Another alternative is to use the LimitRequestBody directive in httpd.conf to limit the size of the request body. This directive can be set per-server, per-directory, per-file, or per-location. The default value is 0, which means unlimited. As an example, to limit the size of the request body to 2 MB, you should add:

LimitRequestBody 2097152

The value is set in bytes (2097152 bytes = = 2 MB).

In this section, we have presented only a single example among many that can cause your server to use more memory than planned. It helps to keep an open mind and to explore what other things a creative user might try to do with your service. Don't assume users will only click where you intend them to.