Sorry for the OT post, but I figure this is a good place to ask, as I'm sure lots of you have solved this one before.(and this is using CGI.pm too :( )
I'm writing a small app that takes an uploaded file from a form, pops it into an obfuscated directory, and then mails out a "here it is" page to an intended recipient of the uploaded file. It's a crudly automated document server of sorts I guess.
I'm not too worried about the upload filenames, but the defensive programmer in me somewhere says if I'm going to write this, I should prevent the uploadee from doing bad things. The uploadee *should* be a trusted user, but may not be... I don't mind a DoS sort of thing, but I don't want them being able to scribble outside the upload directory.
So, can anyone suggest what I should do to the passed filename parameter to make sure it's not "../../../etc/passwd" or somesuch? A simple regex to catch .'s isn't really enough, as I know that can get curcumvented pretty easily these days, and I don't want to maintain it if the work's been done elsewhere already.
my $uploaded_filename = param('uploaded_file');
my $tmpdir = File::Temp::tempdir( "foo_XXXXXX", DIR => $files_dir );
$tmpdir =~ /\/(foo_\w+)$/;
my $shortdir = $1;
print STDERR "$tmpdir\n";
copy($fh, $tmpdir."/".$uploaded_filename);
is the thing I want to make safe. I'm already doing this to it later :
my $safe_uploaded_filename = uri_escape($uploaded_filename);
which is from URI::Escape, but I don't think that will save me :) I know I need to check the return codes from copy etc.
Any belts with a cluestick? I'm not really sure what to google for here.
thanks
Carl