Fix CVE-2018-1000544 absolute path traversal

Small refactor along the way to centralize destination handling when no explicit path is given and a potential malicious one from the zipfile is used
This commit is contained in:
Bart de Water 2018-07-01 14:57:50 -04:00
parent e89f6aca44
commit 6e0d23178a
3 changed files with 34 additions and 4 deletions

View File

@ -147,14 +147,18 @@ module Zip
end
# Extracts entry to file dest_path (defaults to @name).
def extract(dest_path = @name, &block)
block ||= proc { ::Zip.on_exists_proc }
if @name.squeeze('/') =~ /\.{2}(?:\/|\z)/
def extract(dest_path = nil, &block)
if dest_path.nil? && Pathname.new(@name).absolute?
puts "WARNING: skipped absolute path in #{@name}"
return self
elsif @name.squeeze('/') =~ /\.{2}(?:\/|\z)/
puts "WARNING: skipped \"../\" path component(s) in #{@name}"
return self
end
dest_path ||= @name
block ||= proc { ::Zip.on_exists_proc }
if directory? || file? || symlink?
__send__("create_#{@ftype}", dest_path, &block)
else

BIN
test/data/absolutepath.zip Normal file

Binary file not shown.

View File

@ -151,4 +151,30 @@ class ZipEntryTest < MiniTest::Test
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
end