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

Hey all

I'm planning to allow public visitors to upload a plain text file (max 9kb, but usually it'll be around 5-6 kb) so that my script can read the uploaded file and then pre-populate a HTML form.

I know how to carry this out, but just wondering if this is considered safe? If I implement the proper $CGI::POST_MAX value so that it doens't allow anything 9kb or more to be uploaded, am I all set? I also know to check the meta type of the file being uploaded. Since I'm only allowing a plain text file, then I thought it'd be safe. I also know to make sure the uploaded text file has no execute permissions.

The only thing I'm really concerned about now is if someone will build a bot to SPAM it so it uploads a new file every 10 seconds. Is this something that I need to worry about or is this something my HOST will have to implement when configuring the web server? Last question I have is, is it wise to use a CAPTCHA system for this type of uploading feature?

Thanks

Replies are listed 'Best First'.
Re: Upload security question
by jZed (Prior) on Jun 04, 2007 at 00:42 UTC
    The main thing you left off your list of things to watch for is JavasScript cross-site scripting. What do you have in place to prevent a person from putting JavaScript inside the text file that will execute when you display the text as HTML? Perhaps HTML::Strip would come in handy for that part. You are right to worry about possible Denial of Service attacks (continuous uploading). And yes, although it too can be fooled, a CAPTCHA is advisable either on the upload form or on the account-creation form.
      CAPTCHAs can create an accessibility problem, however, and providing an audio alternative isn't always sufficient. Do you know your intended audience well enough to believe this won't be a problem?
      Hey

      thanks for the advice.

        Hi,
        I just read more about how to prevent XSS attacks and it seems like CGI.pm sanitizes most of the incoming form input. Is this not enough? Should I still look into HTML::Strip?

        Thanks.
        Ah, nice, I'll have a look at those next time I need something of the sort, thanks.
Re: Upload security question
by agianni (Hermit) on Jun 04, 2007 at 03:20 UTC

    Assuming that you are expecting the uploaded file to be in a particular format to pre-populate the data correctly, you should probably actually check the format of the contents of the file to ensure it meets your requirements.

    I would say that you should consider running under taint mode and use a regex to check the format of the file, but I don't know if the contents of the file are considered tainted or not (anyone?)

    Also, I'm not sure I'd rely on your server settings to manage file upload size. Of course it would work, but you would potentially be limiting future development as it's a per-server setting. Instead, you might consider using an internal test for this. Data::FormValidator offers a constraint for file size (Data::FormValidator::Constraints::Uploads::file_max_bytes) so you wouldn't have to write it yourself. If you go that route, you can use the D::FV framework to also check the contents of the uploaded file.

    perl -e 'split//,q{john hurl, pest caretaker}and(map{print @_[$_]}(joi +n(q{},map{sprintf(qq{%010u},$_)}(2**2*307*4993,5*101*641*5261,7*59*79 +*36997,13*17*71*45131,3**2*67*89*167*181))=~/\d{2}/g));'
Re: Upload security question
by andreas1234567 (Vicar) on Jun 04, 2007 at 08:00 UTC
Re: Upload security question
by holli (Abbot) on Jun 04, 2007 at 09:37 UTC
    This excellent node contains some useful info about $CGI::POST_MAX and its shortcomings.


    holli, /regexed monk/
Re: Upload security question
by varian (Chaplain) on Jun 04, 2007 at 08:07 UTC
    Some other considerations:
    I also know to make sure the uploaded text file has no execute permissions.
    If there is no need for an uploaded file to be exposed directly to webusers then store the file outside the web server document tree. This limits accidental disclosure via or execution by a web browser.

    On the file size you may also want to set a quota on the amount of bytes used by all uploaded files in total. What happens if say five sessions upload data concurrently? Do they end up in different files? Or do you remove the files after having processed them?

    If the filename is not decided server side then precautions need to be made to ensure that the user cannot overwrite any existing (system) files inside or outside the document tree, e.g. by stating the filesname as './../../somename'

Re: Upload security question
by zentara (Cardinal) on Jun 04, 2007 at 17:26 UTC
    I second holli's recommendation. From my experience, CGI.pm will upload everything first, then determine if it is too big. That leaves you open to denial-of-service attacks. $ENV{CONTENT_LENGTH} is there to detect the incoming size, before it is sent.
    my $maxsize = 1024 * 20000; #max 20M print $query->header(); if($ENV{CONTENT_LENGTH} > $maxsize){ print "file too large - must be less than $maxsize bytes"; exit; }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Upload security question
by Miguel (Friar) on Jun 04, 2007 at 14:59 UTC
    When I need to retrieve a file, via upload forms, I always change the file name before saving on the filesystem, using String::Random and time(). If you need the original file name, keep it on a database table or in a text file.
Re: Upload security question
by Anonymous Monk on Jun 06, 2007 at 22:42 UTC
    Hi, lots of replies! thanks all.

    I have gotten to the point where anytime I deal with placing inputted form values inside a database, I will use placeholders.

    As for the uploaded files, my process is to save and renaming them, and after, delete right away (So I guess the execute permissions code wouldn't matter after-all).

    I'm basically parsing line by line and each line will be assigned to a variable where I'll be passing to HTML::Template to populate the form.

    I also noticed that the max file size will only be 7,800 byte's (~7.6kb). Would a CAPTCHA just be annoying to the user, and I would not need it since a 7800 kb upload post will not really cause too much of a DoS attack??