From bbac5d0d8b6a20487070dc6a298fbb8d9906a538 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 9 Jun 2015 17:07:31 -0700 Subject: raise an exception if the parameters are too deep CVE-2015-3225 --- lib/rack/utils.rb | 15 +++++++++++---- test/spec_utils.rb | 12 ++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb index eea8c879..3b6f69f3 100644 --- a/lib/rack/utils.rb +++ b/lib/rack/utils.rb @@ -61,6 +61,7 @@ module Rack class << self attr_accessor :key_space_limit + attr_accessor :param_depth_limit attr_accessor :multipart_part_limit end @@ -68,6 +69,10 @@ module Rack # This helps prevent a rogue client from flooding a Request. self.key_space_limit = 65536 + # Default depth at which the parameter parser will raise an exception for + # being too deep. This helps prevent SystemStackErrors + self.param_depth_limit = 100 + # The maximum number of parts a request can contain. Accepting too many part # can lead to the server running out of file handles. # Set to `0` for no limit. @@ -126,7 +131,9 @@ module Rack # normalize_params recursively expands parameters into structural types. If # the structural types represented by two different parameter names are in # conflict, a ParameterTypeError is raised. - def normalize_params(params, name, v = nil) + def normalize_params(params, name, v = nil, depth = Utils.param_depth_limit) + raise RangeError if depth <= 0 + name =~ %r(\A[\[\]]*([^\[\]]+)\]*) k = $1 || '' after = $' || '' @@ -146,14 +153,14 @@ module Rack params[k] ||= [] raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) if params_hash_type?(params[k].last) && !params[k].last.key?(child_key) - normalize_params(params[k].last, child_key, v) + normalize_params(params[k].last, child_key, v, depth - 1) else - params[k] << normalize_params(params.class.new, child_key, v) + params[k] << normalize_params(params.class.new, child_key, v, depth - 1) end else params[k] ||= params.class.new raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k]) - params[k] = normalize_params(params[k], after, v) + params[k] = normalize_params(params[k], after, v, depth - 1) end return params diff --git a/test/spec_utils.rb b/test/spec_utils.rb index 06ed5636..c2d479f9 100644 --- a/test/spec_utils.rb +++ b/test/spec_utils.rb @@ -134,6 +134,18 @@ describe Rack::Utils do }.should.not.raise end + should "raise an exception if the params are too deep" do + len = Rack::Utils.param_depth_limit + + lambda { + Rack::Utils.parse_nested_query("foo#{"[a]" * len}=bar") + }.should.raise(RangeError) + + lambda { + Rack::Utils.parse_nested_query("foo#{"[a]" * (len - 1)}=bar") + }.should.not.raise + end + should "parse nested query strings correctly" do Rack::Utils.parse_nested_query("foo"). should.equal "foo" => nil -- cgit v1.2.3-24-ge0c7 From 2a4193dcae6f32d7979c75ebc0692c50ddbdac93 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 9 Jun 2015 17:08:30 -0700 Subject: bump to 1.6.2 --- lib/rack.rb | 2 +- rack.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rack.rb b/lib/rack.rb index 4d49985c..a1fe34d1 100644 --- a/lib/rack.rb +++ b/lib/rack.rb @@ -20,7 +20,7 @@ module Rack # Return the Rack release as a dotted string. def self.release - "1.6.1" + "1.6.2" end PATH_INFO = 'PATH_INFO'.freeze REQUEST_METHOD = 'REQUEST_METHOD'.freeze diff --git a/rack.gemspec b/rack.gemspec index 32c6d797..c2554de1 100644 --- a/rack.gemspec +++ b/rack.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "rack" - s.version = "1.6.1" + s.version = "1.6.2" s.platform = Gem::Platform::RUBY s.summary = "a modular Ruby webserver interface" s.license = "MIT" -- cgit v1.2.3-24-ge0c7 From 90d7d2a8f7ab50cb80adcc05a7fcdd1dfa60f2ad Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 12 Jun 2015 11:40:06 -0700 Subject: update history --- HISTORY.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index b78d8340..1b65179d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,8 @@ +Fri Jun 12 11:37:41 2015 Aaron Patterson + + * Prevent extremely deep parameters from being parsed. CVE-2015-3225 + ### December 18th, Thirty sixth public release 1.6.0 - - TODO ### February 7th, Thirty fifth public release 1.5.2 - Fix CVE-2013-0263, timing attack against Rack::Session::Cookie -- cgit v1.2.3-24-ge0c7