Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
correctly escape backslashes in request path globs
make sure that unreadable files are also not leaked

CVE-2014-7829
  • Loading branch information
tenderlove committed Nov 16, 2014
1 parent 820e294 commit 0d0bc45
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
4 changes: 2 additions & 2 deletions actionpack/lib/action_dispatch/middleware/static.rb
Expand Up @@ -19,7 +19,7 @@ def match?(path)
paths = "#{full_path}#{ext}"

matches = Dir[paths]
match = matches.detect { |m| File.file?(m) }
match = matches.detect { |m| File.file?(m) && File.readable?(m) }
if match
match.sub!(@compiled_root, '')
::Rack::Utils.escape(match)
Expand All @@ -42,7 +42,7 @@ def unescape_path(path)
end

def escape_glob_chars(path)
path.gsub(/[*?{}\[\]]/, "\\\\\\&")
path.gsub(/[*?{}\[\]\\]/, "\\\\\\&")
end

private
Expand Down
41 changes: 41 additions & 0 deletions actionpack/test/dispatch/static_test.rb
@@ -1,5 +1,6 @@
# encoding: utf-8
require 'abstract_unit'
require 'fileutils'
require 'rbconfig'

module StaticTests
Expand Down Expand Up @@ -157,6 +158,46 @@ def public_path

include StaticTests

def test_custom_handler_called_when_file_is_not_readable
filename = 'unreadable.html.erb'
target = File.join(@root, filename)
FileUtils.touch target
File.chmod 0200, target
assert File.exist? target
assert !File.readable?(target)
path = "/#{filename}"
env = {
"REQUEST_METHOD"=>"GET",
"REQUEST_PATH"=> path,
"PATH_INFO"=> path,
"REQUEST_URI"=> path,
"HTTP_VERSION"=>"HTTP/1.1",
"SERVER_NAME"=>"localhost",
"SERVER_PORT"=>"8080",
"QUERY_STRING"=>""
}
assert_equal(DummyApp.call(nil), @app.call(env))
ensure
File.unlink target
end

def test_custom_handler_called_when_file_is_outside_root_backslash
filename = 'shared.html.erb'
assert File.exist?(File.join(@root, '..', filename))
path = "/%5C..%2F#{filename}"
env = {
"REQUEST_METHOD"=>"GET",
"REQUEST_PATH"=> path,
"PATH_INFO"=> path,
"REQUEST_URI"=> path,
"HTTP_VERSION"=>"HTTP/1.1",
"SERVER_NAME"=>"localhost",
"SERVER_PORT"=>"8080",
"QUERY_STRING"=>""
}
assert_equal(DummyApp.call(nil), @app.call(env))
end

def test_custom_handler_called_when_file_is_outside_root
filename = 'shared.html.erb'
assert File.exist?(File.join(@root, '..', filename))
Expand Down

0 comments on commit 0d0bc45

Please sign in to comment.