Skip to content

Commit

Permalink
Merge pull request #446 from avar/avar/fix-issue-405
Browse files Browse the repository at this point in the history
Plack::App::File: Fix a security issue by not pruning trailing slashes
  • Loading branch information
miyagawa committed Feb 7, 2014
2 parents 9c8a5bc + bc1731d commit 458eb93
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
11 changes: 11 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Go to http://github.com/plack/Plack/issues for the roadmap and known issues.

{{$NEXT}}
[SECURITY]
- Plack::App::File would previously strip trailing slashes off
provided paths.

This in combination with the common pattern of dynamically
generating some files in a tree and serving the rest up with
Plack::Middleware::Static could allow an attacker to bypass
a whitelist of generated files by just requesting
/file.disallowed/ instead of /file.disallowed, provided that
Plack::Middleware::Static was used for all paths except
those matching /\.disallowed$/

1.0030 2013-11-23 08:54:01 CET
[IMPROVEMENTS]
Expand Down
2 changes: 1 addition & 1 deletion lib/Plack/App/File.pm
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ sub locate_file {
}

my $docroot = $self->root || ".";
my @path = split /[\\\/]/, $path;
my @path = split /[\\\/]/, $path, -1; # -1 *MUST* be here to avoid security issues!
if (@path) {
shift @path if $path[0] eq '';
} else {
Expand Down
19 changes: 19 additions & 0 deletions t/Plack-Middleware/file.t
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use Plack::Test;
use Test::More;
use HTTP::Request::Common;
use Plack::App::File;
use FindBin qw($Bin);

my $app = Plack::App::File->new(file => 'Changes');

Expand Down Expand Up @@ -35,6 +36,24 @@ test_psgi $app_content_type, sub {
is $res->code, 200;
};

my $app_secure = Plack::App::File->new(root => $Bin);

test_psgi $app_secure, sub {
my $cb = shift;

my $res = $cb->(GET "/file.t");
is $res->code, 200;
like $res->content, qr/We will find for this literal string/;

my $res = $cb->(GET "/../Plack-Middleware/file.t");
is $res->code, 403;
is $res->content, 'forbidden';

for my $i (1..100) {
$res = $cb->(GET "/file.t" . ("/" x $i));
is $res->code, 404;
is $res->content, 'not found';
}
};

done_testing;

0 comments on commit 458eb93

Please sign in to comment.