views:

364

answers:

2

I understand the need to sanitize inputs from a HTML form, but when I sanitized the file upload field in a recent module of mine, the file upload started failing. It's important to sanitize all form inputs, right? Even the special file upload field?

My form output code looks something like this:

use CGI;
my $cgi = new CGI;
print $cgi->header();
# ... print some HTML here
print $cgi->start_form();
print $cgi->filefield(-name=>'uploaded_file',
                      -size=>50,
                      -maxlength=>80);
print $cgi->submit(-name=>'continue',
                   -value=>'Continue');
print $cgi->end_form();
# ... print some more HTML here

And my sanitization code looks something like this (it's actually earlier in the same module as above):

use HTML::Entities
my $OK_CHARS => 'a-zA-Z0-9 .,-_';
foreach my $param_name ( $cgi->param() ) {
    my $original_content = $cgi->param($param_name);
    my $replaced_content = HTML::Entities::decode( $original_content );
    $replaced_content =~ s/[^$OK_CHARS]//go;
    $cgi->param( $param_name, $replaced_content );
}

When I added the sanitization code recently, the file upload started failing. The filehandle is returning undefined now in this line:

my $uploadedFilehandle = $cgi->upload('uploaded_file');

So did I do something wrong in the sanitization code? I got that code snippet from the Internet somewhere, so I don't completely understand it all. I've never seen an 'o' regex modifier before and I've never used the HTML::Entities module before.

+3  A: 

Entities are not encoded in file uploads' content. Sanitizing a file upload is not the same as sanitizing a text field. With a file upload you check the extension and possibly the format and encoding (by attempting to open it using particular decoder, etc.) and ensure that the file is not overly large.

In your code, you are in fact attempting to perform string operations on a file handle when you hit the file field.

Jeff Ober
Oops. I didn't actually realize param('uploaded_file') returned a filehandle. I knew upload('uploaded_file') returned a filehandle. All of the sanitization tutorials I found failed to mention this little complication.
Kurt W. Leucht
@Kurt: It isn't always a filehandle. From CGI.pm: When the form is processed, you can retrieve the entered filename by calling param(): $filename = $query->param('uploaded_file'); Different browsers will return slightly different things for the name. Some browsers return the filename only. Others return the full path to the file ... The filename returned is also a file handle.You should be able to process it as a string, although I agree it's easier to just use the upload() method.
jimtut
Thanks for the explanation. I'm already verifying elsewhere in the code that the uploaded file is the correct type that I'm expecting, so I will just skip over the sanitization of the upload field in the sanitization routine.
Kurt W. Leucht
+2  A: 

No, you should not. See the CGI.pm docs on how to process an upload field:

To be safe, use the upload() function (new in version 2.47). When called with the name of an upload field, upload() returns a filehandle-like object, or undef if the parameter is not a valid filehandle. ...

Sinan Ünür