plack/Plack — pull request #446 by avar (2014-02-07 10:30:54+00:00)
Title: Plack::App::File: Fix a security issue by not pruning trailing slashes

Before this Plack::App::File would prune trailing slashes via its split
invocation. I.e. it would think this:

$ perl -MData::Dumper -wle 'print Dumper [split /[\\\/]/, shift]' a/file.txt
$VAR1 = [
'a',
'file.txt'
];

Was the same as:

$ perl -MData::Dumper -wle 'print Dumper [split /[\\\/]/, shift]' a/file.txt///
$VAR1 = [
'a',
'file.txt'
];

This can. turn into a nasty code exposure issue if you e.g. have an app
that basically does this:

1. I'd do a regex /.txt.pl\z/ on a file to see if it was a text file
2. If so, do magic to generate text file via perl
3. Else it's not a /.txt.pl\z/ file, so it must be some other static
file with a different extension
4. Serve it up with Plack::Middleware::Static

This is also not how other webservers or Unix utilities work:

$ touch /tmp/foo.txt
$ file /tmp/foo.txt
/tmp/foo.txt: empty
$ file /tmp/foo.txt/
/tmp/foo.txt/: ERROR: cannot open `/tmp/foo.txt/' (Not a directory)

This resolves issue #405 that I filed around 9 months ago. I was
previously working around it in my own code by doing:

{
# Let's see if someone's trying to be evil by
# requesting e.g. /index.html/ instead of
# /index.html. We don't want to fall through
# and just serve up the raw content.
my $plack_app_file = Plack::App::File->new({ root => PLACK_WEBSERVER_DOCUMENT_ROOT() });
my ($file) = $plack_app_file->locate_file($env);
if (
# We'll get a reference if it's a full
# Plack response. I.e. a 404 or whatever.
ref $file ne 'ARRAY'
and
# WTF once we canonicalize the file and it
# looks like a Mason handled path let's
# not accept it, because we don't want to
# serve up the raw unprocessed Mason page
# via this hack.
$file =~ $mason_handles_this_path_rx
) {
TELL "Middleware::Static: Path <$path> request, doesn't match <$mason_handles_this_path_rx>, but actually resolves to it via resolved file <$file>" if DEBUG;
# Tells our app to just serve up a
# 400. Apache would do a 404 but I think
# these requests are bad, so say so.
$env->{$magic_marker_to_return_400} = 1;
return;
}
}