Ruby on Rails 路径穿越与任意文件读取漏洞分析 - 【CVE-2019-5418】

栏目: Ruby on Rails · 发布时间: 4年前

内容简介:在控制器中通过

漏洞公告

https://groups.google.com/forum/#!topic/rubyonrails-security/pFRKI96Sm8Q

Versions Affected:  All. 
Not affected:       None. 
Fixed Versions:     6.0.0.beta3, 5.2.2.1, 5.1.6.2, 5.0.7.2, 4.2.11.1 

Impact 
------ 
There is a possible file content disclosure vulnerability in Action View. 
Specially crafted accept headers in combination with calls to `render file:` 
can cause arbitrary files on the target server to be rendered, disclosing the 
file contents. 

The impact is limited to calls to `render` which render file contents without 
a specified accept format.  Impacted code in a controller looks something like 
this: 

    class UserController < ApplicationController 
    def index 
        render file: "#{Rails.root}/some/file" 
    end 
    end

漏洞分析

在控制器中通过 render file 形式来渲染应用之外的视图,因此在 actionview-5.2.1/lib/action_view/renderer/template_renderer.rb:22 中会根据 options.key?(:file) ,调用 find_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

find_file 代码如下:

def find_file(name, prefixes = [], partial = false, keys = [], options = {})
    @view_paths.find_file(*args_for_lookup(name, prefixes, partial, keys, options))
end

继续跟入 args_for_lookup 函数,用于生成用于查找文件的参数,当其最终返回时会把payload保存在 details[formats] 中:

Ruby on Rails 路径穿越与任意文件读取漏洞分析 - 【CVE-2019-5418】

此后回到 @view_paths.find_file 并跟入会进入 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

由于要渲染的视图在应用之外,因此跟入 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

跳过 cached 部分,跟入 find_templates ,这里正式根据条件来查找要渲染的模板:

# 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

build_query后如下:

Ruby on Rails 路径穿越与任意文件读取漏洞分析 - 【CVE-2019-5418】

利用 ../ 与前缀组合造成路径穿越,利用最后的 {{ 完成闭合,经过File.expand_path解析后组成的query如下:

/etc/passwd{{},}{+{},}{.{raw,erb,html,builder,ruby,coffee,jbuilder},}

最后 /etc/passwd 被当成模板文件进行渲染,最后造成了任意文件读取。

漏洞复现

基本环境搭建

# echo "gem 'rails', '5.2.1'" >> Gemfile
# echo "gem 'sqlite3', '~> 1.3.6', '< 1.4'" >> Gemfile
# echo "source 'https://rubygems.org'" >> Gemfile
# bundle exec rails new . --force --skip-bundle

生成控制器:

# rails generate controller chybeta

在 app/controllers/chybeta_controller.rb 中添加:

class ChybetaController < ApplicationController
  def index
    render file: "#{Rails.root}/some/file"
  end
end

在 config/routes.rb 中添加 resources :

Rails.application.routes.draw do
  resources :chybeta
end

可以用命令 rails routes 检查是否存在路由。

修改Accept头为 ../../../../../../../../etc/passwd{{ :

Ruby on Rails 路径穿越与任意文件读取漏洞分析 - 【CVE-2019-5418】

补丁

https://github.com/rails/rails/commit/f4c70c2222180b8d9d924f00af0c7fd632e26715

禁止接受未注册的mime type

Ruby on Rails 路径穿越与任意文件读取漏洞分析 - 【CVE-2019-5418】

以上所述就是小编给大家介绍的《Ruby on Rails 路径穿越与任意文件读取漏洞分析 - 【CVE-2019-5418】》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Hatching Twitter

Hatching Twitter

Nick Bilton / Portfolio Hardcover / 2013-11-5 / USD 28.95

The dramatic, unlikely story behind the founding of Twitter, by New York Times bestselling author and Vanity Fair special correspondent The San Francisco-based technology company Twitter has become......一起来看看 《Hatching Twitter》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具