最新消息:欢迎大家关注安全工具箱微信公众号,域名信息查询,微信搜索安全工具箱添加关注即可,或访问在线安全工具箱

Ruby on Rails 远程代码执行

渗透测试 range 1154浏览 0评论

poweringrails
如果你的应用程序使用的动态模版路径 (例如: render params[:id]) 那么你的程序将会存在远程代码执行和本地文件包含漏洞. 请把你的 Rails升级到最新版本, 或者重构你的controllers。

在这篇博客里我们将展示如何在特定环境下使用代码执行和本地包含漏洞去攻击Ruby on Rails 。
Rails的控制器有包含指定渲染文件的功能,举个例子, 当我们调用 show 方法的时候,如果没有定义其他渲染方法,该框架将会隐藏渲染show.html.erb 文件。
 
在绝大多数情况下,开发者会输出不同的格式,例如:文本, JSON, XML 或者其他任何格式,或者查看一个文件, 在这种情况下, 就会使用一个可以动态渲染的模版语言,例如 ERB, HAML, 或者其他的什么. 但是有几种方法可以修改他们展示的内容, 对我们来说,我们只要盯着渲染的方法就好了. The Rails 的文档定义了几种渲染模版和定义内容的方法 , 包括指定模版的路径的 file 参数
 
如果你已经阅读过解决方法的文档,但是不确定你需不需要这样的功能——实际上并不止你一个人存在这样的疑惑。那么先让我们看看下面这段代码:
  1. def SHOW
  2. render params[:template]
  3. end
这个代码看起来似乎很简单,但是谁也想不到一个控制器只是为了渲染模版, 他定义了一个 template 参数. 但是他没有被过滤过, 然后Rails就会去找指定的模版. , 但是这个模版在哪呢?是views目录,还是根目录,又或者是其他目录? 难道他是期待一个模板文件名,或者是一个特殊后缀的文件名 ,还是说一个完整的路径? 带着这些未知的问题继续探索下去。
问题解答:
 
动态渲染机制是用一个函数解决大量问题的最好的例子。这也就是他的问题所在。
 
让我们假设渲染机制是从 app/views/user/#{params[:template]} 路径读取文件 – 这似乎是一个合理的想法. 如果我们把 template 参数的值设置为  dashboard ,他将为加载 in app/views/user/dashboard.{ext},  .ext 是一个在白名单里的后缀名 (如 .html, .haml, .html.erb, etc.)
那让我们现在想想,如果把 template 的值设置为: ../admin/dashboard. 他将会返回什么样的结果给我们呢? 这可能比较难知道, 但是我们经过尝试时候,他提示我们缺少模版。
通过分析错误提示,可是看出他试图从 RAILS_ROOT/app/viewsRAILS_ROOT 和系统根目录去寻找文件. 这有点让人蛋疼, 因为他为什么要从系统的根目录去寻找我们需要的模版文件呢?
通过黑客的本能反应,我把参数的内容设置为 /etc/passwd , 并且我们确实读取到了 passwd 文件. 这是一个重大的发现.
如果我们能够读取 passwd 文件, 那么我们是不是也能读取应用程序的源码和配置文件呢, 让我们把参数设置为 config/initializers/secrettoken.rb 看看。
别忘了是为什么造成了这样的漏洞,是因为你选择了动态设置模版路径导致的。
  1. def SHOW
  2. render params[:template]
  3. end
这只是一段简单的代码,就能造成这样的漏洞,我相信有不少开发者会这么写,但是这还不是最糟糕的问题。
通过 Jeff Jarmoc 的一篇论文The Anatomy of a Rails Vulnerability – CVE-2014-0130: From Directory Traversal to Shell“ 我们得知,可以通过这样的漏洞获取一个远程代码执行. Jeff’s 的论文介绍了一个在某些版本的 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”命令的值替代。通过如上的方法也可以执行其他的命令了。
 
解决方法:
 
目前来说,最重要的是下载并安装对应ruby版本的补丁
 
如果你不想安装补丁,就不要渲染那些不需要的文本,比如日志文件。通过创建一个可渲染文件hash表,如果请求的渲染文件存在于这个hash表中就返回正常内容,如果不存在,就返回404。在web应用中所有存在动态渲染路径的地方应用这段代码即可:
  1. def SHOW
  2. template = params[:id]
  3. valid_templates = {
  4. "dashboard" => "dashboard",
  5. "profile" => "profile",
  6. "deals" => "deals"
  7. }
  8. if valid_templates.include?(template)
  9. render " #{valid_templates[template]}"
  10. else
  11. # throw exception or 404
  12. end
  13. end
 
另外一个解决方法跟上面一个很相似,通过指定渲染模板的路径和后缀名,判断该模板是否存在,来防止不可知的文件包含:
  1. def SHOW
  2. template = params[:id]
  3. d = Dir["myfolder/*.erb"]
  4. if d.include?("myfolder/#{template}.erb")
  5. render "myfolder/#{template}"
  6. else
  7. # throw exception or 404
  8. end
  9. end
 
你可以使用Brakeman——ruby静态分析工具——来扫描你的web程序。它会报告出你的应用程序中哪些地方存在动态渲染路径,帮助你发现哪些地方存在上述缺陷。
 
结论:
 
如果不去深入地挖掘细节或者积极地尝试exploit,Rails 的渲染机制将是很神秘很难理解的。很遗憾,Rails的参考文档在这方面并没有多大帮助。
 
和CVE-2014-0130类似, 使用动态模板渲染造成了目录遍历和代码执行。我已经不止一次地在很多开源Rails项目中看到过存在这种漏洞了。如果你还没有读过 Jeff Jarmoc的那篇论文,我建议最好先阅读一下,这篇文章深入地挖掘了与CVE-2014-0130相关的漏洞和危害评估。
 
这是我写的可以探测和利用本文所述漏洞的msf module: https://gist.github.com/forced-request/5158759a6418e6376afb

原文地址:
https://nvisium.com/blog/2016/01/26/rails-dynamic-render-to-rce-cve-2016-0752/

转载请注明:安全工具箱 » Ruby on Rails 远程代码执行

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址