8000 Fix CVE-2018-1000544 and disable symlinks to avoid other security issues by jdleesmiller · Pull Request #376 · rubyzip/rubyzip · GitHub
[go: up one dir, main page]

Skip to content

Fix CVE-2018-1000544 and disable symlinks to avoid other security issues #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 31, 2018
Merged
Prev Previous commit
Next Next commit
Consolidate path traversal tests
  • Loading branch information
jdleesmiller committed Aug 26, 2018
commit ffebfa34189a46a766bf6630796c93d81b5ef7ed
3 changes: 3 additions & 0 deletions test/data/path_traversal/tuzovakaoff/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Path Traversal Samples

Copied from https://github.com/jwilk/path-traversal-samples on 2018-08-25.
File renamed without changes.
36 changes: 0 additions & 36 deletions test/entry_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,40 +151,4 @@ def test_store_file_without_compression

assert_match(/mimetypeapplication\/epub\+zip/, first_100_bytes)
end

def test_entry_name_with_absolute_path_does_not_extract
path = '/tmp/file.txt'
File.delete(path) if File.exist?(path)

Zip::File.open('test/data/absolutepath.zip') do |zip_file|
zip_file.each do |entry|
entry.extract
end
end

refute File.exist?(path)
end

def test_entry_name_with_absolute_path_extract_when_given_different_path
path = '/tmp/CVE-2018-1000544'
FileUtils.rm_rf(path) if Dir.exist?(path)

Zip::File.open('test/data/absolutepath.zip') do |zip_file|
zip_file.each do |entry|
entry.extract("#{path}/#{entry.name}")
end
end

assert File.exist?("#{path}/tmp/file.txt")
end

def test_entry_name_with_relative_symlink
assert_raises Errno::ENOENT do
Zip::File.open('test/data/symlink.zip') do |zip_file|
zip_file.each do |entry|
entry.extract
end
end
end
end
end
77 changes: 55 additions & 22 deletions test/path_traversal_test.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
class PathTraversalTest < MiniTest::Test
TEST_FILE_ROOT = File.absolute_path('test/data/jwilk-path-traversal-samples')
TEST_FILE_ROOT = File.absolute_path('test/data/path_traversal')

def setup
FileUtils.rm_f '/tmp/moo' # with apologies to anyone using this file
# With apologies to anyone using these files... but they are the files in
# the sample zips, so we don't have much choice here.
FileUtils.rm_f '/tmp/moo'
FileUtils.rm_f '/tmp/file.txt'
end

def extract_path_traversal_zip(name)
Expand All @@ -17,72 +20,102 @@ def in_tmpdir
Dir.mktmpdir do |tmp|
test_path = File.join(tmp, 'test')
Dir.mkdir test_path
Dir.chdir(test_path) do
yield
Dir.chdir test_path do
yield test_path
end
end
end

def test_leading_slash
in_tmpdir do
extract_path_traversal_zip 'absolute1.zip'
assert !File.exist?('/tmp/moo')
extract_path_traversal_zip 'jwilk/absolute1.zip'
refute File.exist?('/tmp/moo')
end
end

def test_multiple_leading_slashes
in_tmpdir do
extract_path_traversal_zip 'absolute2.zip'
assert !File.exist?('/tmp/moo')
extract_path_traversal_zip 'jwilk/absolute2.zip'
refute File.exist?('/tmp/moo')
end
end

def test_leading_dot_dot
in_tmpdir do
extract_path_traversal_zip 'relative0.zip'
assert !File.exist?('../moo')
extract_path_traversal_zip 'jwilk/relative0.zip'
refute File.exist?('../moo')
end
end

def test_non_leading_dot_dot
in_tmpdir do
extract_path_traversal_zip 'relative2.zip'
assert !File.exist?('../moo')
extract_path_traversal_zip 'jwilk/relative2.zip'
refute File.exist?('../moo')
end
end

def test_file_symlink
in_tmpdir do
extract_path_traversal_zip 'symlink.zip'
extract_path_traversal_zip 'jwilk/symlink.zip'
assert File.exist?('moo')
assert !File.exist?('/tmp/moo')
refute File.exist?('/tmp/moo')
end
end

def test_directory_symlink
in_tmpdir do
extract_path_traversal_zip 'dirsymlink.zip'
assert !File.exist?('/tmp/moo')
extract_path_traversal_zip 'jwilk/dirsymlink.zip'
refute File.exist?('/tmp/moo')
end
end

def test_two_directory_symlinks_a
in_tmpdir do
# Can't create par/moo because the symlink par is skipped.
# Can't create par/moo because the symlinks are skipped.
assert_raises Errno::ENOENT do
extract_path_traversal_zip 'dirsymlink2a.zip'
extract_path_traversal_zip 'jwilk/dirsymlink2a.zip'
end
assert File.exist?('cur')
assert_equal '.', File.readlink('cur')
refute File.exist?('cur')
refute File.exist?('par')
refute File.exist?('par/moo')
end
end

def test_two_directory_symlinks_b
in_tmpdir do
extract_path_traversal_zip 'dirsymlink2b.zip'
extract_path_traversal_zip 'jwilk/dirsymlink2b.zip'
assert File.exist?('cur')
assert_equal '.', File.readlink('cur')
assert !File.exist?('../moo')
refute File.exist?('../moo')
end
end

def test_entry_name_with_absolute_path_does_not_extract
in_tmpdir do
extract_path_traversal_zip 'tuzovakaoff/absolutepath.zip'
refute File.exist?('/tmp/file.txt')
end
end

def test_entry_name_with_absolute_path_extract_when_given_different_path
in_tmpdir do |test_path|
zip_path = File.join(TEST_FILE_ROOT, 'tuzovakaoff/absolutepath.zip')
Zip::File.open(zip_path) do |zip_file|
zip_file.each do |entry|
entry.extract(File.join(test_path, entry.name))
end
end
refute File.exist?('/tmp/file.txt')
end
end

def test_entry_name_with_relative_symlink
in_tmpdir do
# Doesn't create the symlink path, so can't create path/file.txt.
assert_raises Errno::ENOENT do
extract_path_traversal_zip 'tuzovakaoff/symlink.zip'
end
refute File.exist?('/tmp/file.txt')
end
end
end
0