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

Greetings to all,

What sort on checks do you need to perform to ensure that someone has not altered the contents of your html form and then submitting the altered form to the destinated perl script on your server?

I suspect this must be something pretty trivial to do but my search on Google hasn't yielded anything specific.

Hope I've made the question clear...

Thanks in anticipation :)

Updated: Is the code below effective in disallowng submission of an altered form?

# source: fd_board.cgi (with modifications) sub check_url { my @referers = (www.hello.com. hello.com); if ( (!$ENV{'HTTP_REFERER'}) || (!$ENV{'CONTENT_LENGTH'}) || (!$ENV{'HTTP_ACCEPT'}) || (!$ENV{'HTTP_USER_AGENT'})) { &error('bad_headers'); } my $check_referer = 0; foreach my $referer (@referers) { if ($ENV{'HTTP_REFERER'} =~ m|https?://([^/]*)$referer|i) { $check_referer = 1; last; } } if ($check_referer != 1) { &error('bad_referer') } }

janitored by ybiC: Retitle from "CGI script invocation..." for better searching

Replies are listed 'Best First'.
Re: CGI form data validation
by cees (Curate) on Mar 28, 2004 at 04:20 UTC
    Is the code below effective in disallowng submission of an altered form?

    No! It is just as easy to alter the headers as it is to alter the form. You shouldn't focus on whether you think the user changed the form. Instead focus on what values your script expects and make sure that you check those values before you use them.

    Whether or not the user changed the form is irrelevant as long as you only use the parameters that you expect to recieve in your script, and that those parameters contain values that are within your given constraints.

    I would suggest you do some reading on CGI programming and security. A good place to start is probably Ovid's CGI course. Or check out some of the other CGI Tutorials here at the monestary.

    - Cees

Re: CGI form data validation
by cees (Curate) on Mar 28, 2004 at 04:04 UTC

    You can never trust any data that comes from outside of your program. That especially goes for HTML forms. Your program needs to know what parameters are expected in the script, and it needs to check the values to make sure they are valid.

    This is actually easier to do than it seems with a module like Data::FormValidator. Here is a quick example, but have a read of the documentation for more details.

    my $profile = { required => [qw( cc_type cc_name cc_number cc_expiry cc_3digit_code )], constraints => { # field must match one of visa amex or mc cc_type => qr/^(visa|amex|mc)$/, # match to a name cc_name => qr/^([\w ]+)$/, # use built in cc_number function to validate # credit card numbers. the validation # routine needs both the cc_number and the # cc_type to do the validation cc_number => { constraint => 'cc_number', params => [qw(cc_number cc_type)] }, # use the builting cc_exp routine to validate # the expiry date cc_expiry => 'cc_exp', # field must be a 3 or 4 word or # digit characters cc_3digit_code => qr/^([\w\d]{3,4})$/, }, }; # Check the profile to make sure everything was filled in correctly my $query = CGI->new(); my $results = Data::FormValidator->check($query, $profile); if ($results->has_invalid or $results->has_missing) { # There were some problems with the form values # so redisplay the form ... } else { # The form was properly filled out my $valid = $results->valid(); # now $valid contains a hashref of all the validated data # so do something with the values ... }

    The above is a simple example of how to validate credit card details.

    - Cees

Re: CGI form data validation
by Anonymous Monk on Mar 28, 2004 at 03:45 UTC

    It takes quite a bit, but once you've mastered a technique or two, it becomes simple habit. Essentially, you should be checking every bit of data that comes in and making sure it contains only what should be allowed. This includes checking lengths of fields (never rely on HTML's 'maxlength' attribute to limit input length) and making sure that any hidden fields contain what you think they do.

    The second you find yourself stuffing data into hidden fields, you're most likely wanting to implement a system that maintains user sessions. This way any important information is placed on your server (in some sort of database) where the user can't modify it manually.

    You should try restricting the characters used in fields as much as possible (for example, if you are accepting phone numbers, you might try restricting the field to only allow digits, spaces, hyphens and parentheses). And then come checkboxes, radio buttons, select fields. You need to check that the values coming in through these are valid. You might only put 'Chocolate' and 'Vanilla' as options to a select field, but someone can copy the html over and insert their own 'Strawberry' flavour if they'd like.

    It's hard to give a full-blown tutorial without writing a book on the subject. Validating data is trivial but at the same time can be a lot of work in some situations. One final note: if you're ever going to use javascript to validate form fields (which is Evil in itself), you still need to validate data on the server side of things. Relying on javascript validation is even worse than relying on the 'maxlength' attribute, because even legit users who are not trying to hack your script apart will be able to submit invalid data if they don't have javascript enabled.

    So long post made short: you need to check all incoming data to make sure it is exactly what you are expecting. It's that simple :)

Re: CGI form data validation
by ctilmes (Vicar) on Mar 28, 2004 at 02:39 UTC
    You make the assumption that someone could very well have altered the contents of your html form in the most dangerous possible way. You think of every way that they could have altered it and check each and every parameter to ensure that it has valid values, regardless of what the form looked like.

      You think of every way that they could have altered it [...]
      Having quite some imagination, that's an endless task.

      I would rather advise not to care if anybody has tempered with the form, but
      only focus on making sure that the expected values that were filled in

      • are inside their required range and
      • only contain quality input:
      Simply throw away all other data submitted that you don't expect/need.

Re: CGI form data validation
by blue_cowdawg (Monsignor) on Mar 28, 2004 at 02:55 UTC

        What sort on checks do you need to perform to ensure that someone has not altered the contents of your html form and then submitting the altered form to the destinated perl script on your server?

    Short answer: it depends.

    First I'm not sure if you are asking about the structure of the form itself, or that data within that form. If you are talking about the data itself then you are going to have to do some data validation work.

    Develop an idea of what your data should look like and develop code to validate it.

    Unfortunately without more information about what your exposure and risks are I can't give you a better answer.


    Peter L. Berghold -- Unix Professional
    Peter at Berghold dot Net
       Dog trainer, dog agility exhibitor, brewer of fine Belgian style ales. Happiness is a warm, tired, contented dog curled up at your side and a good Belgian ale in your chalice.
Re: CGI form data validation
by saintmike (Vicar) on Mar 29, 2004 at 02:33 UTC
    You might want to take a look at CGI::Untaint, which will help you make sure you're not overlooking checking the validity of any of the input parameters by using Perl's tainting mechanism.

    CGI::Untaint was nicely introduced in Perl Advent Calendar 2003.

    -- saintmike