Ruby on Rails 入门及CVE-2016-0752远程代码执行漏洞研究

0x00 Ruby on Rails 简介


Ruby 是什么?

你说呢?

PHP是最好的语言。

Rails 是什么?

Rails 是使用 Ruby 语言编写的网页程序开发框架,目的是为开发者提供常用组件,简化网页程序的开发。只需编写较少的代码,就能实现其他编程语言或框架难以企及的功能。经验丰富的 Rails 程序员会发现,Rails 让程序开发变得更有乐趣。

0x01 Ruby on Rails 环境搭建


主要参考ruby社区文章:https://ruby-china.org/wiki/install_ruby_guide

文章中部分命令有误(估计是过时了),贴下我执行的命令情况:

$ curl -L https://get.rvm.io | bash -s stable

$ gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

$ curl -L https://get.rvm.io | bash -s stable

$ source /etc/profile.d/rvm.sh

$ rvm -v
rvm 1.26.11 (latest) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]

第一步 RVM 安装完成,接下来用 RVM 安装 Ruby 环境;

$ rvm install 2.2.4

ruby官网查看版本号,我选择的是:Previous stable: Ruby 2.2.4,没选最新的 2.3.0 ,怕有坑,新手入门还是选择历史稳定版好点。

1454039747505.png

安装完成,设置下默认版本

$ rvm 2.2.4 --default

测试下配置是否正确

$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-linux]

$ gem -v
2.4.8

$ gem source -r https://rubygems.org
https://rubygems.org/ removed from sources

$ gem source -a https://ruby.taobao.org
https://ruby.taobao.org added to sources

安装 Bundler

$ gem install bundler

至此,Ruby 环境就已经安装好了,接下来安装 Rails。

$ gem install rails

然后测试安装是否成功。

$ rails -v
Rails 4.2.5.1

0x02 创建第一个应用(Hello World)

Rails 提供了多个被称为“生成器”的脚本,可以简化开发,生成某项操作需要的所有文件。其中一个是新程序生成器,生成一个 Rails 程序骨架,不用自己一个一个新建文件。

$ mkdir -p /home/learn-ruby/workspace && cd /home/learn-ruby/workspace

$ rails new hello_world

$ ll
total 4
drwxr-xr-x 12 root root 4096 Jan 29 00:11 hello_world

$ cd hello_world/

$ ll
total 60
drwxr-xr-x 8 root root 4096 Jan 29 00:10 app
drwxr-xr-x 2 root root 4096 Jan 29 00:11 bin
drwxr-xr-x 5 root root 4096 Jan 29 00:10 config
-rw-r--r-- 1 root root  153 Jan 29 00:10 config.ru
drwxr-xr-x 2 root root 4096 Jan 29 00:10 db
-rw-r--r-- 1 root root 1504 Jan 29 00:10 Gemfile
-rw-r--r-- 1 root root 3952 Jan 29 00:11 Gemfile.lock
drwxr-xr-x 4 root root 4096 Jan 29 00:10 lib
drwxr-xr-x 2 root root 4096 Jan 29 00:10 log
drwxr-xr-x 2 root root 4096 Jan 29 00:10 public
-rw-r--r-- 1 root root  249 Jan 29 00:10 Rakefile
-rw-r--r-- 1 root root  478 Jan 29 00:10 README.rdoc
drwxr-xr-x 8 root root 4096 Jan 29 00:10 test
drwxr-xr-x 3 root root 4096 Jan 29 00:10 tmp
drwxr-xr-x 3 root root 4096 Jan 29 00:10 vendor

可以看到 hello_world 文件夹中有很多自动生成的文件和文件夹,这些组成一个 Rails 程序。下面简单介绍默认生成的文件和文件夹的作用:

文件/文件夹 作用
app/ 存放程序的控制器、模型、视图、帮助方法、邮件和静态资源文件。本文主要关注的是这个文件夹。
bin/ 存放运行程序的 rails 脚本,以及其他用来部署或运行程序的脚本。
config/ 设置程序的路由,数据库等。详情参阅“设置 Rails 程序”一文。
config.ru 基于 Rack 服务器的程序设置,用来启动程序。
db/ 存放当前数据库的模式,以及数据库迁移文件。
Gemfile, Gemfile.lock 这两个文件用来指定程序所需的 gem 依赖件,用于 Bundler gem。关于 Bundler 的详细介绍,请访问 Bundler 官网
lib/ 程序的扩展模块。
log/ 程序的日志文件。
public/ 唯一对外开放的文件夹,存放静态文件和编译后的资源文件。
Rakefile 保存并加载可在命令行中执行的任务。任务在 Rails 的各组件中定义。如果想添加自己的任务,不要修改这个文件,把任务保存在 lib/tasks 文件夹中。
README.rdoc 程序的简单说明。你应该修改这个文件,告诉其他人这个程序的作用,如何安装等。
test/ 单元测试,固件等测试用文件。详情参阅“测试 Rails 程序”一文。
tmp/ 临时文件,例如缓存,PID,会话文件。
vendor/ 存放第三方代码。经常用来放第三方 gem。

要使程序能够被访问,我们需要先开启web server

$ rails server

上述命令会启动 WEBrick,这是 Ruby 内置的服务器。要查看程序,请打开一个浏览器窗口,访问 http://localhost:3000。应该会看到默认的 Rails 信息页面:

rails_welcome.png

PS:
Q:如何使程序监听在 0.0.0.0 ?
A:在 config/boot.rb 文件中添加如下代码,然后再次执行 rails server 即可。

require 'rails/commands/server'

module Rails
  class Server
    alias :default_options_bk :default_options
    def default_options
      default_options_bk.merge!(Host: '0.0.0.0')
    end
  end
end

Q:如何更改监听端口?
A:rails server -p 12345 加 -p 参数指定端口号。

接下来开始写自己的程序,Rails 也是基于 MVC 模式进行开发的,那我们首先创建个控制器(Controller)和视图(View)。

控制器用来接受向程序发起的请求。路由决定哪个控制器会接受到这个请求。一般情况下,每个控制器都有多个路由,对应不同的动作。动作用来提供视图中需要的数据。

视图的作用是,以人类能看懂的格式显示数据。有一点要特别注意,数据是在控制器中获取的,而不是在视图中。视图只是把数据显示出来。默认情况下,视图使用 eRuby(嵌入式 Ruby)语言编写,经由 Rails 解析后,再发送给用户。

Rails 很高级,创建控制器可用 控制器生成器 工具来自动创建,只需告诉生成器,我想要个名为“welcome”的控制器和一个名为“index”的动作,命令如下所示:

$ rails generate controller welcome index

生成的控制器文件在 app/controllers/welcome_controller.rb,内容如下:

class WelcomeController < ApplicationController
  def index
  end
end

视图文件在 app/views/welcome/index.html.erb ,我们编辑它,将内容修改为:

<h1>Hello, Rails!</h1>

然后访问看下效果:

1454049918392.png

至此,我们已经写完第一个 Rails 应用了。

0x03 CVE-2016-0752 远程代码执行漏洞研究

从上文我们可以看到,在控制器中并没有说明要加载哪个视图文件,这是Rails 的一个特性。

Rails controllers 的设计中,会根据被调用的方法,隐式的渲染对应的 view 文件。例如上文中,当调用 welcomeindex 方法时,如果代码中没有明确指定要渲染的 view file,框架就会隐式的渲染 index.html.erb 文件。

CVE-2016-0752 漏洞用到的是渲染方法(render method)。Rails 的文档中给出了多种调用渲染方法的方式,包括使用 file: 选项来明确指定要渲染的 view file 路径。

来看一段示例代码:

def show
  render params[:template]
end

第一眼看,这段代码非常简单,主要功能为渲染 template 参数指定的 view 模板。但Rails如何查找指定的模板呢?在 views 目录下查找? 在应用的 root 目录下查找?或是在其他位置?;该参数的值是一个模板的名称?是一个有特定后缀的文件名?或是一个完整的文件路径?

后续内容 http://drops.wooyun.org/papers/12519

标签: ruby, rails

添加新评论