diff options
Diffstat (limited to 'spec/ruby/security')
| -rw-r--r-- | spec/ruby/security/cve_2010_1330_spec.rb | 10 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2011_4815_spec.rb | 4 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2013_4164_spec.rb | 4 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2014_8080_spec.rb | 32 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2017_17742_spec.rb | 34 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2018_16396_spec.rb | 14 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2018_6914_spec.rb | 61 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2018_8778_spec.rb | 6 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2018_8779_spec.rb | 8 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2018_8780_spec.rb | 42 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2019_8321_spec.rb | 20 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2019_8322_spec.rb | 24 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2019_8323_spec.rb | 46 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2019_8325_spec.rb | 46 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2020_10663_spec.rb | 49 | ||||
| -rw-r--r-- | spec/ruby/security/cve_2024_49761_spec.rb | 7 |
16 files changed, 252 insertions, 155 deletions
diff --git a/spec/ruby/security/cve_2010_1330_spec.rb b/spec/ruby/security/cve_2010_1330_spec.rb index c41a5e0a2e..8867fb7135 100644 --- a/spec/ruby/security/cve_2010_1330_spec.rb +++ b/spec/ruby/security/cve_2010_1330_spec.rb @@ -1,7 +1,6 @@ require_relative '../spec_helper' describe "String#gsub" do - it "resists CVE-2010-1330 by raising an exception on invalid UTF-8 bytes" do # This original vulnerability talked about KCODE, which is no longer # used. Instead we are forcing encodings here. But I think the idea is the @@ -9,13 +8,12 @@ describe "String#gsub" do # #gsub on a string in the UTF-8 encoding but with invalid an UTF-8 byte # sequence. - str = "\xF6<script>" - str.force_encoding Encoding::ASCII_8BIT + str = +"\xF6<script>" + str.force_encoding Encoding::BINARY str.gsub(/</, "<").should == "\xF6<script>".b str.force_encoding Encoding::UTF_8 - lambda { + -> { str.gsub(/</, "<") - }.should raise_error(ArgumentError, /invalid byte sequence in UTF-8/) + }.should.raise(ArgumentError, /invalid byte sequence in UTF-8/) end - end diff --git a/spec/ruby/security/cve_2011_4815_spec.rb b/spec/ruby/security/cve_2011_4815_spec.rb index 02ef10d562..554e014a1f 100644 --- a/spec/ruby/security/cve_2011_4815_spec.rb +++ b/spec/ruby/security/cve_2011_4815_spec.rb @@ -35,9 +35,7 @@ describe "String#hash" do end describe "Symbol#hash" do - ruby_bug "#13376", "2.3.0"..."2.3.4" do - it_behaves_like :resists_cve_2011_4815, ':a' - end + it_behaves_like :resists_cve_2011_4815, ':a' end describe "Array#hash" do diff --git a/spec/ruby/security/cve_2013_4164_spec.rb b/spec/ruby/security/cve_2013_4164_spec.rb index 94578cc7ce..d223b8fd5e 100644 --- a/spec/ruby/security/cve_2013_4164_spec.rb +++ b/spec/ruby/security/cve_2013_4164_spec.rb @@ -3,17 +3,13 @@ require_relative '../spec_helper' require 'json' describe "String#to_f" do - it "resists CVE-2013-4164 by converting very long Strings to a Float" do "1.#{'1'*1000000}".to_f.should be_close(1.1111111111111112, TOLERANCE) end - end describe "JSON.parse" do - it "resists CVE-2013-4164 by converting very long Strings to a Float" do JSON.parse("[1.#{'1'*1000000}]").first.should be_close(1.1111111111111112, TOLERANCE) end - end diff --git a/spec/ruby/security/cve_2014_8080_spec.rb b/spec/ruby/security/cve_2014_8080_spec.rb deleted file mode 100644 index e9d7fd320c..0000000000 --- a/spec/ruby/security/cve_2014_8080_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -require_relative '../spec_helper' - -require 'rexml/document' - -describe "REXML::Document.new" do - - it "resists CVE-2014-8080 by raising an exception when entity expansion has grown too large" do - xml = <<XML - <?xml version="1.0" encoding="UTF-8" ?> - <!DOCTYPE x [ - <!ENTITY % x0 "xxxxxxxxxx"> - <!ENTITY % x1 "%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;"> - <!ENTITY % x2 "%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;"> - <!ENTITY % x3 "%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;"> - <!ENTITY % x4 "%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;"> - <!ENTITY % x5 "%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;"> - <!ENTITY % x6 "%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;"> - <!ENTITY % x7 "%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;"> - <!ENTITY % x8 "%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;"> - <!ENTITY % x9 "%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;"> - ]> - <x> - %x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9; - </x> -XML - - lambda { - REXML::Document.new(xml).doctype.entities['x9'].value - }.should raise_error(REXML::ParseException, /entity expansion has grown too large/) - end - -end diff --git a/spec/ruby/security/cve_2017_17742_spec.rb b/spec/ruby/security/cve_2017_17742_spec.rb deleted file mode 100644 index 72776cb497..0000000000 --- a/spec/ruby/security/cve_2017_17742_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require_relative '../spec_helper' - -require "webrick" -require "stringio" -require "net/http" - -describe "WEBrick" do - describe "resists CVE-2017-17742" do - it "for a response splitting headers" do - config = WEBrick::Config::HTTP - res = WEBrick::HTTPResponse.new config - res['X-header'] = "malicious\r\nCookie: hack" - io = StringIO.new - res.send_response io - io.rewind - res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) - res.code.should == '500' - io.string.should_not =~ /hack/ - end - - it "for a response splitting cookie headers" do - user_input = "malicious\r\nCookie: hack" - config = WEBrick::Config::HTTP - res = WEBrick::HTTPResponse.new config - res.cookies << WEBrick::Cookie.new('author', user_input) - io = StringIO.new - res.send_response io - io.rewind - res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io)) - res.code.should == '500' - io.string.should_not =~ /hack/ - end - end -end diff --git a/spec/ruby/security/cve_2018_16396_spec.rb b/spec/ruby/security/cve_2018_16396_spec.rb index e462e0022d..6f8a5d2f5d 100644 --- a/spec/ruby/security/cve_2018_16396_spec.rb +++ b/spec/ruby/security/cve_2018_16396_spec.rb @@ -1,21 +1,7 @@ require_relative '../spec_helper' describe "Array#pack" do - - it "resists CVE-2018-16396 by tainting output based on input" do - "aAZBbHhuMmPp".each_char do |f| - ["123456".taint].pack(f).tainted?.should be_true - end - end - end describe "String#unpack" do - - it "resists CVE-2018-16396 by tainting output based on input" do - "aAZBbHhuMm".each_char do |f| - "123456".taint.unpack(f).first.tainted?.should be_true - end - end - end diff --git a/spec/ruby/security/cve_2018_6914_spec.rb b/spec/ruby/security/cve_2018_6914_spec.rb index a40225799d..f0aedb0dc6 100644 --- a/spec/ruby/security/cve_2018_6914_spec.rb +++ b/spec/ruby/security/cve_2018_6914_spec.rb @@ -1,56 +1,55 @@ require_relative '../spec_helper' require 'tempfile' +require 'tmpdir' describe "CVE-2018-6914 is resisted by" do - before :all do - @traversal_path = Array.new(Dir.pwd.split('/').count, '..').join('/') + Dir.pwd + '/' - @traversal_path.delete!(':') if /mswin|mingw/ =~ RUBY_PLATFORM + before :each do + @tmpdir = ENV['TMPDIR'] + @dir = tmp("CVE-2018-6914") + Dir.mkdir(@dir, 0700) + ENV['TMPDIR'] = @dir + @dir << '/' + + @tempfile = nil + end + + after :each do + ENV['TMPDIR'] = @tmpdir + @tempfile.close! if @tempfile + rm_r @dir end it "Tempfile.open by deleting separators" do - begin - expect = Dir.glob(@traversal_path + '*').count - t = Tempfile.open([@traversal_path, 'foo']) - actual = Dir.glob(@traversal_path + '*').count - actual.should == expect - ensure - t.close! - end + @tempfile = Tempfile.open(['../', 'foo']) + actual = @tempfile.path + File.absolute_path(actual).should.start_with?(@dir) end it "Tempfile.new by deleting separators" do - begin - expect = Dir.glob(@traversal_path + '*').count - t = Tempfile.new(@traversal_path + 'foo') - actual = Dir.glob(@traversal_path + '*').count - actual.should == expect - ensure - t.close! - end + @tempfile = Tempfile.new('../foo') + actual = @tempfile.path + File.absolute_path(actual).should.start_with?(@dir) end it "Tempfile.create by deleting separators" do - expect = Dir.glob(@traversal_path + '*').count - Tempfile.create(@traversal_path + 'foo') do - actual = Dir.glob(@traversal_path + '*').count - actual.should == expect + actual = Tempfile.create('../foo') do |t| + t.path end + File.absolute_path(actual).should.start_with?(@dir) end it "Dir.mktmpdir by deleting separators" do - expect = Dir.glob(@traversal_path + '*').count - Dir.mktmpdir(@traversal_path + 'foo') do - actual = Dir.glob(@traversal_path + '*').count - actual.should == expect + actual = Dir.mktmpdir('../foo') do |path| + path end + File.absolute_path(actual).should.start_with?(@dir) end it "Dir.mktmpdir with an array by deleting separators" do - expect = Dir.glob(@traversal_path + '*').count - Dir.mktmpdir([@traversal_path, 'foo']) do - actual = Dir.glob(@traversal_path + '*').count - actual.should == expect + actual = Dir.mktmpdir(['../', 'foo']) do |path| + path end + File.absolute_path(actual).should.start_with?(@dir) end end diff --git a/spec/ruby/security/cve_2018_8778_spec.rb b/spec/ruby/security/cve_2018_8778_spec.rb index a264a8581e..bbdaac734c 100644 --- a/spec/ruby/security/cve_2018_8778_spec.rb +++ b/spec/ruby/security/cve_2018_8778_spec.rb @@ -1,12 +1,10 @@ require_relative '../spec_helper' describe "String#unpack" do - it "resists CVE-2018-8778 by raising an exception when a position indicator is larger than a native integer" do pos = (1 << PlatformGuard::POINTER_SIZE) - 99 - lambda { + -> { "0123456789".unpack("@#{pos}C10") - }.should raise_error(RangeError, /pack length too big/) + }.should.raise(RangeError, /pack length too big/) end - end diff --git a/spec/ruby/security/cve_2018_8779_spec.rb b/spec/ruby/security/cve_2018_8779_spec.rb index 9659b321ee..6d573ea7fd 100644 --- a/spec/ruby/security/cve_2018_8779_spec.rb +++ b/spec/ruby/security/cve_2018_8779_spec.rb @@ -16,15 +16,15 @@ platform_is_not :windows do end it "UNIXServer.open by raising an exception when there is a NUL byte" do - lambda { + -> { UNIXServer.open(@path+"\0") - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) + }.should.raise(ArgumentError, /(path name|string) contains null byte/) end it "UNIXSocket.open by raising an exception when there is a NUL byte" do - lambda { + -> { UNIXSocket.open(@path+"\0") - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) + }.should.raise(ArgumentError, /(path name|string) contains null byte/) end end end diff --git a/spec/ruby/security/cve_2018_8780_spec.rb b/spec/ruby/security/cve_2018_8780_spec.rb index febb1de51d..dc8c6bcc9b 100644 --- a/spec/ruby/security/cve_2018_8780_spec.rb +++ b/spec/ruby/security/cve_2018_8780_spec.rb @@ -6,42 +6,38 @@ describe "CVE-2018-8780 is resisted by" do end it "Dir.glob by raising an exception when there is a NUL byte" do - lambda { + -> { Dir.glob([[@root, File.join(@root, "*")].join("\0")]) - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) + }.should.raise(ArgumentError, /(path name|string) contains null byte/) end it "Dir.entries by raising an exception when there is a NUL byte" do - lambda { + -> { Dir.entries(@root+"\0") - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) + }.should.raise(ArgumentError, /(path name|string) contains null byte/) end it "Dir.foreach by raising an exception when there is a NUL byte" do - lambda { + -> { Dir.foreach(@root+"\0").to_a - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) + }.should.raise(ArgumentError, /(path name|string) contains null byte/) end - ruby_version_is "2.4" do - it "Dir.empty? by raising an exception when there is a NUL byte" do - lambda { - Dir.empty?(@root+"\0") - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) - end + it "Dir.empty? by raising an exception when there is a NUL byte" do + -> { + Dir.empty?(@root+"\0") + }.should.raise(ArgumentError, /(path name|string) contains null byte/) end - ruby_version_is "2.5" do - it "Dir.children by raising an exception when there is a NUL byte" do - lambda { - Dir.children(@root+"\0") - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) - end + it "Dir.children by raising an exception when there is a NUL byte" do + -> { + Dir.children(@root+"\0") + }.should.raise(ArgumentError, /(path name|string) contains null byte/) + end - it "Dir.each_child by raising an exception when there is a NUL byte" do - lambda { - Dir.each_child(@root+"\0").to_a - }.should raise_error(ArgumentError, /(path name|string) contains null byte/) - end + it "Dir.each_child by raising an exception when there is a NUL byte" do + -> { + Dir.each_child(@root+"\0").to_a + }.should.raise(ArgumentError, /(path name|string) contains null byte/) end end diff --git a/spec/ruby/security/cve_2019_8321_spec.rb b/spec/ruby/security/cve_2019_8321_spec.rb new file mode 100644 index 0000000000..a8a86e7d97 --- /dev/null +++ b/spec/ruby/security/cve_2019_8321_spec.rb @@ -0,0 +1,20 @@ +require_relative '../spec_helper' + +require 'rubygems' +require 'rubygems/user_interaction' + +describe "CVE-2019-8321 is resisted by" do + it "sanitising verbose messages" do + ui = Class.new { + include Gem::UserInteraction + }.new + ui.should_receive(:say).with(".]2;nyan.") + verbose_before = Gem.configuration.verbose + begin + Gem.configuration.verbose = :really_verbose + ui.verbose("\e]2;nyan\a") + ensure + Gem.configuration.verbose = verbose_before + end + end +end diff --git a/spec/ruby/security/cve_2019_8322_spec.rb b/spec/ruby/security/cve_2019_8322_spec.rb new file mode 100644 index 0000000000..dbc273f313 --- /dev/null +++ b/spec/ruby/security/cve_2019_8322_spec.rb @@ -0,0 +1,24 @@ +require_relative '../spec_helper' + +ruby_version_is ""..."4.0" do + + require 'yaml' + require 'rubygems' + require 'rubygems/safe_yaml' + require 'rubygems/commands/owner_command' + + describe "CVE-2019-8322 is resisted by" do + it "sanitising owner names" do + command = Gem::Commands::OwnerCommand.new + def command.rubygems_api_request(*args) + Struct.new(:body).new("---\n- email: \"\e]2;nyan\a\"\n handle: handle\n id: id\n") + end + def command.with_response(response) + yield response + end + command.should_receive(:say).with("Owners for gem: name") + command.should_receive(:say).with("- .]2;nyan.") + command.show_owners "name" + end + end +end diff --git a/spec/ruby/security/cve_2019_8323_spec.rb b/spec/ruby/security/cve_2019_8323_spec.rb new file mode 100644 index 0000000000..49a31a6682 --- /dev/null +++ b/spec/ruby/security/cve_2019_8323_spec.rb @@ -0,0 +1,46 @@ +require_relative '../spec_helper' + +require 'optparse' + +require 'rubygems' +require 'rubygems/gemcutter_utilities' + +describe "CVE-2019-8323 is resisted by" do + describe "sanitising the body" do + it "for success codes" do + cutter = Class.new { + include Gem::GemcutterUtilities + }.new + klass = if defined?(Gem::Net::HTTPSuccess) + Gem::Net::HTTPSuccess + else + Net::HTTPSuccess + end + response = klass.new(nil, nil, nil) + def response.body + "\e]2;nyan\a" + end + cutter.should_receive(:say).with(".]2;nyan.") + cutter.with_response response + end + + it "for error codes" do + cutter = Class.new { + include Gem::GemcutterUtilities + }.new + def cutter.terminate_interaction(n) + end + klass = if defined?(Gem::Net::HTTPNotFound) + Gem::Net::HTTPNotFound + else + Net::HTTPNotFound + end + response = klass.new(nil, nil, nil) + def response.body + "\e]2;nyan\a" + end + cutter.should_receive(:say).with(".]2;nyan.") + cutter.with_response response + end + end +end diff --git a/spec/ruby/security/cve_2019_8325_spec.rb b/spec/ruby/security/cve_2019_8325_spec.rb new file mode 100644 index 0000000000..bbddb3a6ce --- /dev/null +++ b/spec/ruby/security/cve_2019_8325_spec.rb @@ -0,0 +1,46 @@ +require_relative '../spec_helper' + +require 'rubygems' +require 'rubygems/command_manager' + +describe "CVE-2019-8325 is resisted by" do + describe "sanitising error message components" do + before :each do + @ui = Gem::SilentUI.new + end + + after :each do + @ui.close + end + + it "for the 'while executing' message" do + manager = Gem::CommandManager.new + manager.ui = @ui + def manager.process_args(args, build_args) + raise StandardError, "\e]2;nyan\a" + end + def manager.terminate_interaction(n) + end + manager.should_receive(:alert_error).with("While executing gem ... (StandardError)\n .]2;nyan.") + manager.run nil, nil + end + + it "for the 'invalid option' message" do + manager = Gem::CommandManager.new + def manager.terminate_interaction(n) + end + manager.should_receive(:alert_error).with("Invalid option: --.]2;nyan.. See 'gem --help'.") + manager.process_args ["--\e]2;nyan\a"], nil + end + + it "for the 'loading command' message" do + manager = Gem::CommandManager.new + manager.ui = @ui + def manager.require(x) + raise 'foo' + end + manager.should_receive(:alert_error).with("Loading command: .]2;nyan. (RuntimeError)\n\tfoo") + manager.send :load_and_instantiate, "\e]2;nyan\a" + end + end +end diff --git a/spec/ruby/security/cve_2020_10663_spec.rb b/spec/ruby/security/cve_2020_10663_spec.rb new file mode 100644 index 0000000000..7f42c40742 --- /dev/null +++ b/spec/ruby/security/cve_2020_10663_spec.rb @@ -0,0 +1,49 @@ +require_relative '../spec_helper' + +ruby_version_is ""..."4.0" do + require 'json' + + module JSONSpecs + class MyClass + def initialize(foo) + @foo = foo + end + + def self.json_create(hash) + new(*hash['args']) + end + + def to_json(*args) + { 'json_class' => self.class.name, 'args' => [ @foo ] }.to_json(*args) + end + end + end + + guard -> { + JSON.const_defined?(:Pure) or + version_is(JSON::VERSION, '2.3.0'...'2.11.0') + } do + describe "CVE-2020-10663 is resisted by" do + it "only creating custom objects if passed create_additions: true or using JSON.load" do + obj = JSONSpecs::MyClass.new("bar") + JSONSpecs::MyClass.should.json_creatable? + json = JSON.dump(obj) + + JSON.parse(json, create_additions: true).class.should == JSONSpecs::MyClass + JSON(json, create_additions: true).class.should == JSONSpecs::MyClass + if version_is(JSON::VERSION, '2.8.0') + warning = /\Wcreate_additions:\s*true\W\s+is\s+deprecated/ + else + warning = '' + end + -> { + JSON.load(json).class.should == JSONSpecs::MyClass + }.should output_to_fd(warning, STDERR) + + JSON.parse(json).class.should == Hash + JSON.parse(json, nil).class.should == Hash + JSON(json).class.should == Hash + end + end + end +end diff --git a/spec/ruby/security/cve_2024_49761_spec.rb b/spec/ruby/security/cve_2024_49761_spec.rb new file mode 100644 index 0000000000..c66b438eef --- /dev/null +++ b/spec/ruby/security/cve_2024_49761_spec.rb @@ -0,0 +1,7 @@ +require_relative '../spec_helper' + +describe "CVE-2024-49761 is resisted by" do + it "the Regexp implementation handling that regular expression in linear time" do + Regexp.linear_time?(/�*((?:\d+)|(?:x[a-fA-F0-9]+));/).should == true + end +end |
