CVE-2018-1000075 (published 2018-03-13T15:29Z)

RubyGems version Ruby 2.2 series: 2.2.9 and earlier, Ruby 2.3 series: 2.3.6 and earlier, Ruby 2.4 series: 2.4.3 and earlier, Ruby 2.5 series: 2.5.0 and earlier, prior to trunk revision 62422 contains a infinite loop caused by negative size vulnerability in ruby gem package tar header that can result in a negative size could cause an infinite loop.. This vulnerability appears to have been fixed in 2.7.6.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-835
cwe_name: Loop with Unreachable Exit Condition ('Infinite Loop')
description: The product contains an iteration or loop with an exit condition that cannot be reached, i.e., an infinite loop.
extended_description: If the loop can be influenced by an attacker, this weakness could allow attackers to consume excessive resources such as CPU or memory.
         

Fix information:
repo_url: https://github.com/rubygems/rubygems
commit_details: repo_url: https://github.com/rubygems/rubygems
author: Samuel Giddins
author_date: 2018-02-11 22:00:03-08:00
msg: 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.
repository: repo_url: https://github.com/rubygems/rubygems
repo_name: rubygems/rubygems
description: Library packaging and distribution for Ruby.
repo_language: Ruby
owner: rubygems
file_changes: filename: tar_header.rb
change_type: ModificationType.MODIFY
diff: @@ -104,25 +104,30 @@ def self.from(stream)
     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+
 

programming_language: Ruby
filename: test_gem_package_tar_header.rb
change_type: ModificationType.MODIFY
diff: @@ -143,5 +143,25 @@ def test_update_checksum
     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
 

programming_language: Ruby