开发者 John Hawthorn 公开了 Ruby on Rails 上的一个路径穿越与任意文件读取漏洞。
John 指出,Action View 中可能存在文件内容泄露漏洞。特制的 accept headers 并调用 render file,可以导致目标服务器上的任意文件被渲染,从而泄露文件内容。控制器中受影响的代码如上图所示。 漏洞分析在控制器中通过 module ActionView
class TemplateRenderer < AbstractRenderer #:nodoc:
# Determine the template to be rendered using the given options.
def determine_template(options)
keys = options.has_key?(:locals) ? options[:locals].keys : []
if options.key?(:body)
...
elsif options.key?(:file)
with_fallbacks { find_file(options[:file], nil, false, keys, @details) }
...
end
end
def find_file(name, prefixes = [], partial = false, keys = [], options = {})
@view_paths.find_file(*args_for_lookup(name, prefixes, partial, keys, options))
end
用于生成查找文件参数的
它会执行位于 actionview-5.2.1/lib/action_view/path_set.rb 中的 class PathSet #:nodoc:
def find_file(path, prefixes = [], *args)
_find_all(path, prefixes, args, true).first || raise(MissingTemplate.new(self, path, prefixes, *args))
end
private
# 注,这里的 args 即前面args_for_lookup生成的details
def _find_all(path, prefixes, args, outside_app)
prefixes = [prefixes] if String === prefixes
prefixes.each do |prefix|
paths.each do |resolver|
if outside_app
templates = resolver.find_all_anywhere(path, prefix, *args)
else
templates = resolver.find_all(path, prefix, *args)
end
return templates unless templates.empty?
end
end
[]
end
因为视图在应用之外,所以 outside_app equals == True,并调用 find_all_anywhere: def find_all_anywhere(name, prefix, partial = false, details = {}, key = nil, locals = [])
cached(key, [name, prefix, partial], details, locals) do
find_templates(name, prefix, partial, details, true)
end
end
跳过 # An abstract class that implements a Resolver with path semantics.
class PathResolver < Resolver #:nodoc:
EXTENSIONS = { locale: ".", formats: ".", variants: "+", handlers: "." }
DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}"
...
private
def find_templates(name, prefix, partial, details, outside_app_allowed = false)
path = Path.build(name, prefix, partial)
# 注意 details 与 details[:formats] 的传入
query(path, details, details[:formats], outside_app_allowed)
end
def query(path, details, formats, outside_app_allowed)
query = build_query(path, details)
template_paths = find_template_paths(query)
...
end
end
利用
最后 该漏洞已被 CVE 收录,编号 CVE-2019-5418、CVE-2019-5419,目前补丁已经跟进:https://github.com/rails/rails/commit/f4c70c2222180b8d9d924f00af0c7fd632e26715 禁止接受未注册的 mime types: 详情查看漏洞报告:https://github.com/mpgn/CVE-2019-5418#cve-2019-5418---file-content-disclosure-on-rails |