Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
correctly escape backslashes in request path globs
Conflicts:
	actionpack/lib/action_dispatch/middleware/static.rb

make sure that unreadable files are also not leaked

CVE-2014-7829
  • Loading branch information
tenderlove committed Nov 16, 2014
1 parent 03366b1 commit 307402f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
5 changes: 3 additions & 2 deletions actionpack/lib/action_dispatch/middleware/static.rb
Expand Up @@ -16,7 +16,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 @@ -40,14 +40,15 @@ def unescape_path(path)

def escape_glob_chars(path)
path.force_encoding('binary') if path.respond_to? :force_encoding
path.gsub(/[*?{}\[\]]/, "\\\\\\&")
path.gsub(/[*?{}\[\]\\]/, "\\\\\\&")
end

private

PATH_SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact)

def clean_path_info(path_info)
path_info.force_encoding('binary') if path_info.respond_to? :force_encoding
parts = path_info.split PATH_SEPS

clean = []
Expand Down
41 changes: 41 additions & 0 deletions actionpack/test/dispatch/static_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
require 'fileutils'
require 'rbconfig'

module StaticTests
Expand Down Expand Up @@ -149,6 +150,46 @@ def setup

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 307402f

Please sign in to comment.