diff -Nru ruby2.0-2.0.0.484/debian/changelog ruby2.0-2.0.0.484/debian/changelog --- ruby2.0-2.0.0.484/debian/changelog 2017-12-18 19:31:11.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/changelog 2018-04-03 18:45:04.000000000 +0000 @@ -1,3 +1,41 @@ +ruby2.0 (2.0.0.484-1ubuntu2.6) trusty-security; urgency=medium + + * SECURITY UPDATE: Directory traversal + - debian/patches/CVE-2018-1000073.patch: fix in + lib/rubygems/package.rb. + - CVE-2018-1000073 + * SECURITY UPDATE: Deserialization untrusted data + - debian/patches/CVE-2018-1000074.patch fix in + lib/rubygems/commands/owner_command.rb, + test/rubygems/test_gem_commands_owner_command.rb. + - CVE-2018-1000074 + * SECURITY UPDATE: Infinite loop + - debian/patches/CVE-2018-1000075.patch: fix in + lib/rubygems/package/tar_header.rb, + test/rubygems/test_gem_package_tar_header.rb. + - CVE-2018-1000075 + * SECURITY UPDATE: Improper verification of crypto + signature + - debian/patches/CVE-2018-1000076.patch: fix in + lib/rubygems/package.rb, lib/rubygems/pacage/tar_writer.rb, + test/rubygems/test_gem_pacakge.rg + - CVE-2018-1000076 + * SECURITY UPDATE: Validation vulnerability + - debian/patches/CVE-2018-1000077.patch: fix in + lib/rubygems/specification.rb, + test/rubygems/test_gem_specification.rb. + - CVE-2018-1000077 + * SECURITY UPDATE: Cross site scripting + - debian/patches/CVE-2018-1000078.patch: fix in + lib/rubygems/server.rb. + - CVE-2018-1000078 + * SECURITY UPDATE: Directory traversal + - debian/patches/CVE-2018-1000079.patch: fix in + lib/rubygems/package.rb, test/rubygems/test_gem_package.rb. + - CVE-2018-1000079 + + -- Leonidas S. Barbosa Tue, 03 Apr 2018 15:37:15 -0300 + ruby2.0 (2.0.0.484-1ubuntu2.5) trusty-security; urgency=medium * SECURITY UPDATE: command injection through Net::FTP diff -Nru ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000073.patch ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000073.patch --- ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000073.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000073.patch 2018-04-03 18:36:30.000000000 +0000 @@ -0,0 +1,19 @@ +Backported of: + +From 1b931fc03b819b9a0214be3eaca844ef534175e2 Mon Sep 17 00:00:00 2001 +From: Jonathan Claudius +Date: Wed, 7 Feb 2018 23:54:52 -0500 +Subject: [PATCH] Non-working patch for deducing symlinked base-dirs +diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb +index 9574462..6214058 100644 +--- a/lib/rubygems/package.rb ++++ b/lib/rubygems/package.rb +@@ -371,6 +371,8 @@ EOM + File.respond_to? :realpath + + destination = File.join destination_dir, filename ++ destination = File.realpath destination if ++ File.respond_to? :realpath + destination = File.expand_path destination + + raise Gem::Package::PathError.new(destination, destination_dir) unless diff -Nru ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000074.patch ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000074.patch --- ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000074.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000074.patch 2018-04-03 18:36:36.000000000 +0000 @@ -0,0 +1,66 @@ +Backported of: + +From 254e3d0ee873c008c0b74e8b8abcbdab4caa0a6d Mon Sep 17 00:00:00 2001 +From: Jonathan Claudius +Date: Mon, 12 Feb 2018 23:41:28 -0500 +Subject: [PATCH] Fix possible Unsafe Object Deserialization Vulnerability in + gem owner + +diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb +index 11e6e02..df64f41 100644 +--- a/lib/rubygems/commands/owner_command.rb ++++ b/lib/rubygems/commands/owner_command.rb +@@ -48,7 +48,7 @@ class Gem::Commands::OwnerCommand < Gem::Command + end + + with_response response do |resp| +- owners = YAML.load resp.body ++ owners = Gem::SafeYAML.load resp.body + + say "Owners for gem: #{name}" + owners.each do |owner| +diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb +index dfbc257..e6b8e40 100644 +--- a/test/rubygems/test_gem_commands_owner_command.rb ++++ b/test/rubygems/test_gem_commands_owner_command.rb +@@ -1,6 +1,9 @@ + require 'rubygems/test_case' + require 'rubygems/commands/owner_command' + ++class Foo ++end ++ + class TestGemCommandsOwnerCommand < Gem::TestCase + + def setup +@@ -34,6 +37,30 @@ EOF + assert_match %r{- user2@example.com}, @ui.output + end + ++ def test_show_owners_dont_load_objects ++ skip "testing a psych-only API" unless defined?(::Psych::DisallowedClass) ++ ++ response = < +Date: Sun, 11 Feb 2018 22:00:03 -0800 +Subject: [PATCH] Strictly interpret octal fields in tar headers + +Any octal field that contains characters other that 0-7 will cause acn +exception to be raised. + +This prevents a negative size from being set, which could cause an +infinite loop. +diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb +index 28da1db..7d75ff5 100644 +--- a/lib/rubygems/package/tar_header.rb ++++ b/lib/rubygems/package/tar_header.rb +@@ -103,25 +103,30 @@ class Gem::Package::TarHeader + fields = header.unpack UNPACK_FORMAT + + new :name => fields.shift, +- :mode => fields.shift.oct, +- :uid => fields.shift.oct, +- :gid => fields.shift.oct, +- :size => fields.shift.oct, +- :mtime => fields.shift.oct, +- :checksum => fields.shift.oct, ++ :mode => strict_oct(fields.shift), ++ :uid => strict_oct(fields.shift), ++ :gid => strict_oct(fields.shift), ++ :size => strict_oct(fields.shift), ++ :mtime => strict_oct(fields.shift), ++ :checksum => strict_oct(fields.shift), + :typeflag => fields.shift, + :linkname => fields.shift, + :magic => fields.shift, +- :version => fields.shift.oct, ++ :version => strict_oct(fields.shift), + :uname => fields.shift, + :gname => fields.shift, +- :devmajor => fields.shift.oct, +- :devminor => fields.shift.oct, ++ :devmajor => strict_oct(fields.shift), ++ :devminor => strict_oct(fields.shift), + :prefix => fields.shift, + + :empty => empty + end + ++ def self.strict_oct(str) ++ return str.oct if str =~ /\A[0-7]*\z/ ++ raise ArgumentError, "#{str.inspect} is not an octal string" ++ end ++ + ## + # Creates a new TarHeader using +vals+ + +diff --git a/test/rubygems/test_gem_package_tar_header.rb b/test/rubygems/test_gem_package_tar_header.rb +index 5d85543..0ddb440 100644 +--- a/test/rubygems/test_gem_package_tar_header.rb ++++ b/test/rubygems/test_gem_package_tar_header.rb +@@ -126,5 +126,25 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 + assert_equal '012467', @tar_header.checksum + end + ++ def test_from_bad_octal ++ test_cases = [ ++ "00000006,44\000", # bogus character ++ "00000006789\000", # non-octal digit ++ "+0000001234\000", # positive sign ++ "-0000001000\000", # negative sign ++ "0x000123abc\000", # radix prefix ++ ] ++ ++ test_cases.each do |val| ++ header_s = @tar_header.to_s ++ # overwrite the size field ++ header_s[124, 12] = val ++ io = TempIO.new header_s ++ assert_raises ArgumentError do ++ new_header = Gem::Package::TarHeader.from io ++ end ++ end ++ end ++ + end + diff -Nru ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000076.patch ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000076.patch --- ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000076.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000076.patch 2018-04-03 18:36:48.000000000 +0000 @@ -0,0 +1,94 @@ +Backported of: + +From f5042b879259b1f1ce95a0c5082622c646376693 Mon Sep 17 00:00:00 2001 +From: Samuel Giddins +Date: Sun, 11 Feb 2018 20:47:37 -0800 +Subject: [PATCH] Raise a security error when there are duplicate files in a + package + +This is a rudimentary fix for an issue where RubyGems would allow a +mis-signed gem to be installed, as the tarball would contain multiple +gem signatures. + +Nothing should give us a tarball with multiple entries, so we'll just +disallow that. +diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb +index 6214058..555d5bc 100644 +--- a/lib/rubygems/package.rb ++++ b/lib/rubygems/package.rb +@@ -543,6 +543,10 @@ EOM + raise Gem::Package::FormatError.new \ + 'package content (data.tar.gz) is missing', @gem + end ++ ++ if duplicates = @files.group_by {|f| f }.select {|k,v| v.size > 1 }.map(&:first) and duplicates.any? ++ raise Gem::Security::Exception, "duplicate files in the package: (#{duplicates.map(&:inspect).join(', ')})" ++ end + end + + ## +diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb +index f2c11e3..0fbc177 100644 +--- a/lib/rubygems/package/tar_writer.rb ++++ b/lib/rubygems/package/tar_writer.rb +@@ -176,6 +176,8 @@ class Gem::Package::TarWriter + digest.name == signer.digest_name + end + ++ raise "no #{signer.digest_name} in #{digests.values.compact}" unless signature_digest ++ + signature = signer.sign signature_digest.digest + + add_file_simple "#{name}.sig", 0444, signature.length do |io| +diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb +index c77fc47..fa1dc39 100644 +--- a/test/rubygems/test_gem_package.rb ++++ b/test/rubygems/test_gem_package.rb +@@ -514,6 +514,32 @@ class TestGemPackage < Gem::Package::TarTestCase + assert_match %r%nonexistent.gem$%, e.message + end + ++ def test_verify_duplicate_file ++ FileUtils.mkdir_p 'lib' ++ FileUtils.touch 'lib/code.rb' ++ ++ build = Gem::Package.new @gem ++ build.spec = @spec ++ build.setup_signer ++ open @gem, 'wb' do |gem_io| ++ Gem::Package::TarWriter.new gem_io do |gem| ++ build.add_metadata gem ++ build.add_contents gem ++ ++ gem.add_file_simple 'a.sig', 0444, 0 ++ gem.add_file_simple 'a.sig', 0444, 0 ++ end ++ end ++ ++ package = Gem::Package.new @gem ++ ++ e = assert_raises Gem::Security::Exception do ++ package.verify ++ end ++ ++ assert_equal 'duplicate files in the package: ("a.sig")', e.message ++ end ++ + def test_verify_security_policy + package = Gem::Package.new @gem + package.security_policy = Gem::Security::HighSecurity +@@ -565,7 +591,13 @@ class TestGemPackage < Gem::Package::TarTestCase + + # write bogus data.tar.gz to foil signature + bogus_data = Gem.gzip 'hello' +- gem.add_file_simple 'data.tar.gz', 0444, bogus_data.length do |io| ++ fake_signer = Class.new do ++ def digest_name; 'SHA512'; end ++ def digest_algorithm; Digest(:SHA512); end ++ def key; 'key'; end ++ def sign(*); 'fake_sig'; end ++ end ++ gem.add_file_signed 'data2.tar.gz', 0444, fake_signer.new do |io| + io.write bogus_data + end + diff -Nru ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000077.patch ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000077.patch --- ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000077.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000077.patch 2018-04-03 18:36:55.000000000 +0000 @@ -0,0 +1,63 @@ +Backported of: + +From feadefc2d351dcb95d6492f5ad17ebca546eb964 Mon Sep 17 00:00:00 2001 +From: Jonathan Claudius +Date: Fri, 2 Feb 2018 00:09:29 -0500 +Subject: [PATCH] Enforce URL validation on spec homepage attribute +diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb +index cc31c89..6327b4c 100644 +--- a/lib/rubygems/specification.rb ++++ b/lib/rubygems/specification.rb +@@ -9,6 +9,7 @@ require 'rubygems/version' + require 'rubygems/requirement' + require 'rubygems/platform' + require 'rubygems/deprecate' ++require 'uri' + + # :stopdoc: + # date.rb can't be loaded for `make install` due to miniruby +@@ -2472,10 +2473,16 @@ class Gem::Specification + raise Gem::InvalidSpecificationException, "#{lazy} is not a summary" + end + +- if homepage and not homepage.empty? and +- homepage !~ /\A[a-z][a-z\d+.-]*:/i then +- raise Gem::InvalidSpecificationException, +- "\"#{homepage}\" is not a URI" ++ # Make sure a homepage is valid HTTP/HTTPS URI ++ if homepage and not homepage.empty? ++ begin ++ homepage_uri = URI.parse(homepage) ++ unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class ++ raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a URI" ++ end ++ rescue URI::InvalidURIError ++ raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a URI" ++ end + end + + # Warnings +diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb +index 9c1064e..71746cf 100644 +--- a/test/rubygems/test_gem_specification.rb ++++ b/test/rubygems/test_gem_specification.rb +@@ -1587,6 +1587,19 @@ end + end + + assert_equal '"over at my cool site" is not a URI', e.message ++ ++ @a1.homepage = 'ftp://rubygems.org' ++ ++ e = assert_raises Gem::InvalidSpecificationException do ++ @a1.validate ++ end ++ ++ assert_equal '"ftp://rubygems.org" is not a URI', e.message ++ ++ @a1.homepage = 'http://rubygems.org' ++ ++ assert_equal true, @a1.validate ++ + end + end + diff -Nru ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000078.patch ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000078.patch --- ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000078.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000078.patch 2018-04-03 18:37:00.000000000 +0000 @@ -0,0 +1,19 @@ +Backported of: + +From 66a28b9275551384fdab45f3591a82d6b59952cb Mon Sep 17 00:00:00 2001 +From: Jonathan Claudius +Date: Thu, 1 Feb 2018 23:04:33 -0500 +Subject: [PATCH] Fix 289313 +diff --git a/lib/rubygems/server.rb b/lib/rubygems/server.rb +index f2d1428..246d99a 100644 +--- a/lib/rubygems/server.rb ++++ b/lib/rubygems/server.rb +@@ -604,7 +604,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; } + "only_one_executable" => (executables && executables.size == 1), + "full_name" => spec.full_name, + "has_deps" => !deps.empty?, +- "homepage" => spec.homepage, ++ "homepage" => (URI.parse(spec.homepage).is_a?(URI::HTTP) || URI.parse(spec.homepage).is_a?(URI::HTTPS)) ? spec.homepage : ".", + "name" => spec.name, + "rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?, + "ri_installed" => Gem::RDoc.new(spec).ri_installed?, diff -Nru ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000079.patch ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000079.patch --- ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000079.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/patches/CVE-2018-1000079.patch 2018-04-03 18:37:06.000000000 +0000 @@ -0,0 +1,105 @@ +Backported of: + +From f83f911e19e27cbac1ccce7471d96642241dd759 Mon Sep 17 00:00:00 2001 +From: Jonathan Claudius +Date: Thu, 1 Feb 2018 00:00:48 -0500 +Subject: [PATCH] Add bug fix for #270068 + +From 666ef793cad42eed96f7aee1cdf77865db921099 Mon Sep 17 00:00:00 2001 +From: Samuel Giddins +Date: Sun, 11 Feb 2018 21:44:58 -0800 +Subject: [PATCH] Implement a safe mkdir for package that verifies were inside + the destination dir for all new directories ccreated + +diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb +index 555d5bc..f475f85 100644 +--- a/lib/rubygems/package.rb ++++ b/lib/rubygems/package.rb +@@ -332,7 +332,16 @@ EOM + + FileUtils.rm_rf destination + +- FileUtils.mkdir_p File.dirname destination ++ mkdir_options = {} ++ mkdir_options[:mode] = entry.header.mode if entry.directory? ++ mkdir = ++ if entry.directory? then ++ destination ++ else ++ File.dirname destination ++ end ++ ++ mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name + + open destination, 'wb', entry.header.mode do |out| + out.write entry.read +@@ -367,21 +376,34 @@ EOM + raise Gem::Package::PathError.new(filename, destination_dir) if + filename.start_with? '/' + +- destination_dir = File.realpath destination_dir if +- File.respond_to? :realpath ++ destination_dir = realpath destination_dir + + destination = File.join destination_dir, filename +- destination = File.realpath destination if +- File.respond_to? :realpath + destination = File.expand_path destination + + raise Gem::Package::PathError.new(destination, destination_dir) unless +- destination.start_with? destination_dir ++ destination.start_with? destination_dir + '/' + + destination.untaint + destination + end + ++ def mkdir_p_safe mkdir, mkdir_options, destination_dir, file_name ++ destination_dir = realpath File.expand_path(destination_dir) ++ parts = mkdir.split(File::SEPARATOR) ++ parts.reduce do |path, basename| ++ path = realpath path unless path == "" ++ path = File.expand_path(path + File::SEPARATOR + basename) ++ lstat = File.lstat path rescue nil ++ if !lstat || !lstat.directory? ++ unless path.start_with? destination_dir and (FileUtils.mkdir path, mkdir_options rescue false) ++ raise Gem::Package::PathError.new(file_name, destination_dir) ++ end ++ end ++ path ++ end ++ end ++ + ## + # Loads a Gem::Specification from the TarEntry +entry+ + +@@ -560,6 +582,16 @@ EOM + raise Gem::Package::FormatError.new(e.message, entry.full_name) + end + ++ if File.respond_to? :realpath ++ def realpath file ++ File.realpath file ++ end ++ else ++ def realpath file ++ file ++ end ++ end ++ + end + + require 'rubygems/package/digest_io' +diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb +index fa1dc39..afb79fe 100644 +--- a/test/rubygems/test_gem_package.rb ++++ b/test/rubygems/test_gem_package.rb +@@ -305,7 +305,7 @@ class TestGemPackage < Gem::Package::TarTestCase + package.extract_tar_gz tgz_io, @destination + end + +- assert_equal("installing into parent path /absolute.rb of " + ++ assert_equal("installing into parent path lib/link/outside.txt of " + + "#{@destination} is not allowed", e.message) + end + diff -Nru ruby2.0-2.0.0.484/debian/patches/series ruby2.0-2.0.0.484/debian/patches/series --- ruby2.0-2.0.0.484/debian/patches/series 2017-12-19 13:45:43.000000000 +0000 +++ ruby2.0-2.0.0.484/debian/patches/series 2018-04-03 18:37:06.000000000 +0000 @@ -11,3 +11,10 @@ CVE-2016-7798.patch fix_tests.patch CVE-2017-17405.patch +CVE-2018-1000073.patch +CVE-2018-1000074.patch +CVE-2018-1000075.patch +CVE-2018-1000076.patch +CVE-2018-1000077.patch +CVE-2018-1000078.patch +CVE-2018-1000079.patch