CVE-2018-1000074 (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 Deserialization of Untrusted Data vulnerability in owner command that can result in code execution. This attack appear to be exploitable via victim must run the `gem owner` command on a gem with a specially crafted YAML file. This vulnerability appears to have been fixed in 2.7.6.

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

Weakness information:
cwe_id: CWE-502
cwe_name: Deserialization of Untrusted Data
description: The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.
extended_description: 
            It is often convenient to serialize objects for communication or to save them for later use. However, deserialized data or code can often be modified without using the provided accessor functions if it does not use cryptography to protect itself. Furthermore, any cryptography would still be client-side security -- which is a dangerous security assumption.
            Data that is untrusted can not be trusted to be well-formed.
            When developers place no restrictions on "gadget chains," or series of instances and method invocations that can self-execute during the deserialization process (i.e., before the object is returned to the caller), it is sometimes possible for attackers to leverage them to perform unauthorized actions, like generating a shell.
         
         

Fix information:
repo_url: https://github.com/rubygems/rubygems
commit_details: repo_url: https://github.com/rubygems/rubygems
author: Jonathan Claudius
author_date: 2018-02-12 23:41:28-05:00
msg: Fix possible Unsafe Object Deserialization Vulnerability in gem owner
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: owner_command.rb
change_type: ModificationType.MODIFY
diff: @@ -64,7 +64,7 @@ def show_owners name
     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|

programming_language: Ruby
filename: test_gem_commands_owner_command.rb
change_type: ModificationType.MODIFY
diff: @@ -2,6 +2,9 @@
 require 'rubygems/test_case'
 require 'rubygems/commands/owner_command'
 
+class Foo
+end
+
 class TestGemCommandsOwnerCommand < Gem::TestCase
 
   def setup
@@ -43,6 +46,31 @@ def test_show_owners
     assert_match %r{- 4}, @ui.output
   end
 
+  def test_show_owners_dont_load_objects
+    skip "testing a psych-only API" unless defined?(::Psych::DisallowedClass)
+
+    response = <<EOF
+---
+- email: !ruby/object:Foo {}
+  id: 1
+  handle: user1
+- email: user2@example.com
+- id: 3
+  handle: user3
+- id: 4
+EOF
+
+    @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
+
+    assert_raises Psych::DisallowedClass do
+      use_ui @ui do
+        @cmd.show_owners("freewill")
+      end
+    end
+
+  end
+
+
   def test_show_owners_setting_up_host_through_env_var
     response = "- email: user1@example.com\n"
     host = "http://rubygems.example"

programming_language: Ruby