diff --git a/2-2-header-redos.patch b/2-2-header-redos.patch new file mode 100644 index 0000000000000000000000000000000000000000..37f7078cab93e1b70367e0832e309ee3c7330cf0 --- /dev/null +++ b/2-2-header-redos.patch @@ -0,0 +1,31 @@ +From ee7919ea04303717858be1c3f16b406adc6d8cff Mon Sep 17 00:00:00 2001 +From: Aaron Patterson +Date: Mon, 13 Mar 2023 10:58:13 -0700 +Subject: [PATCH] Avoid ReDoS problem + +Split headers on commas, then strip the strings in order to avoid ReDoS +issues. + +[CVE-2023-27539] +--- + lib/rack/request.rb | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/rack/request.rb b/lib/rack/request.rb +index 750a0dc4..fea98459 100644 +--- a/lib/rack/request.rb ++++ b/lib/rack/request.rb +@@ -572,8 +572,8 @@ module Rack + end + + def parse_http_accept_header(header) +- header.to_s.split(/\s*,\s*/).map do |part| +- attribute, parameters = part.split(/\s*;\s*/, 2) ++ header.to_s.split(",").each(&:strip!).map do |part| ++ attribute, parameters = part.split(";", 2).each(&:strip!) + quality = 1.0 + if parameters and /\Aq=([\d.]+)/ =~ parameters + quality = $1.to_f +-- +2.37.1 + diff --git a/2-2-multipart-dos.patch b/2-2-multipart-dos.patch new file mode 100644 index 0000000000000000000000000000000000000000..53c68a37224238ffb1bff96ec8ec0f92e3ea3329 --- /dev/null +++ b/2-2-multipart-dos.patch @@ -0,0 +1,138 @@ +From 9aac3757fe19cdb0476504c9245170115bec9668 Mon Sep 17 00:00:00 2001 +From: John Hawthorn +Date: Thu, 8 Dec 2022 15:54:28 -0800 +Subject: [PATCH] Limit all multipart parts, not just files + +Previously we would limit the number of multipart parts which were +files, but not other parts. In some cases this could cause parsing of +maliciously crafted inputs to take longer than expected. + +[CVE-2023-27530] +--- + README.rdoc | 20 +++++++++++++++++--- + lib/rack/multipart/parser.rb | 19 +++++++++++++++---- + lib/rack/utils.rb | 19 +++++++++++++++---- + 3 files changed, 76 insertions(+), 12 deletions(-) + +diff --git a/README.rdoc b/README.rdoc +index 8533846f..cbb25723 100644 +--- a/README.rdoc ++++ b/README.rdoc +@@ -202,16 +202,30 @@ Limiting the depth prevents a possible stack overflow when parsing parameters. + + Defaults to 100. + +-=== multipart_part_limit ++=== multipart_file_limit + +-The maximum number of parts a request can contain. ++The maximum number of parts with a filename a request can contain. + Accepting too many part can lead to the server running out of file handles. + + The default is 128, which means that a single request can't upload more than 128 files at once. + + Set to 0 for no limit. + +-Can also be set via the +RACK_MULTIPART_PART_LIMIT+ environment variable. ++Can also be set via the +RACK_MULTIPART_FILE_LIMIT+ environment variable. ++ ++(This is also aliased as +multipart_part_limit+ and +RACK_MULTIPART_PART_LIMIT+ for compatibility) ++ ++=== multipart_total_part_limit ++ ++The maximum total number of parts a request can contain of any type, including ++both file and non-file form fields. ++ ++The default is 4096, which means that a single request can't contain more than ++4096 parts. ++ ++Set to 0 for no limit. ++ ++Can also be set via the +RACK_MULTIPART_TOTAL_PART_LIMIT+ environment variable. + + == Changelog + +diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb +index e8ed3e97..0fc18560 100644 +--- a/lib/rack/multipart/parser.rb ++++ b/lib/rack/multipart/parser.rb +@@ -5,6 +5,7 @@ require 'strscan' + module Rack + module Multipart + class MultipartPartLimitError < Errno::EMFILE; end ++ class MultipartTotalPartLimitError < StandardError; end + + class Parser + (require_relative '../core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4' +@@ -140,7 +141,7 @@ module Rack + + @mime_parts[mime_index] = klass.new(body, head, filename, content_type, name) + +- check_open_files ++ check_part_limits + end + + def on_mime_body(mime_index, content) +@@ -152,13 +153,23 @@ module Rack + + private + +- def check_open_files +- if Utils.multipart_part_limit > 0 +- if @open_files >= Utils.multipart_part_limit ++ def check_part_limits ++ file_limit = Utils.multipart_file_limit ++ part_limit = Utils.multipart_total_part_limit ++ ++ if file_limit && file_limit > 0 ++ if @open_files >= file_limit + @mime_parts.each(&:close) + raise MultipartPartLimitError, 'Maximum file multiparts in content reached' + end + end ++ ++ if part_limit && part_limit > 0 ++ if @mime_parts.size >= part_limit ++ @mime_parts.each(&:close) ++ raise MultipartTotalPartLimitError, 'Maximum total multiparts in content reached' ++ end ++ end + end + end + +diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb +index 14d9e17d..c8e61ea1 100644 +--- a/lib/rack/utils.rb ++++ b/lib/rack/utils.rb +@@ -58,13 +58,24 @@ module Rack + end + + class << self +- attr_accessor :multipart_part_limit ++ attr_accessor :multipart_total_part_limit ++ ++ attr_accessor :multipart_file_limit ++ ++ # multipart_part_limit is the original name of multipart_file_limit, but ++ # the limit only counts parts with filenames. ++ alias multipart_part_limit multipart_file_limit ++ alias multipart_part_limit= multipart_file_limit= + end + +- # The maximum number of parts a request can contain. Accepting too many part +- # can lead to the server running out of file handles. ++ # The maximum number of file parts a request can contain. Accepting too ++ # many parts can lead to the server running out of file handles. + # Set to `0` for no limit. +- self.multipart_part_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || 128).to_i ++ self.multipart_file_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || ENV['RACK_MULTIPART_FILE_LIMIT'] || 128).to_i ++ ++ # The maximum total number of parts a request can contain. Accepting too ++ # many can lead to excessive memory use and parsing time. ++ self.multipart_total_part_limit = (ENV['RACK_MULTIPART_TOTAL_PART_LIMIT'] || 4096).to_i + + def self.param_depth_limit + default_query_parser.param_depth_limit +-- +2.37.1 + diff --git a/rubygem-rack.spec b/rubygem-rack.spec index be2310906984bd3ba1b5f9037e41c1b1da73caa9..89791ab5c16e2c142ab082f898b3e333f93ab394 100644 --- a/rubygem-rack.spec +++ b/rubygem-rack.spec @@ -3,7 +3,7 @@ Name: rubygem-%{gem_name} Version: 2.2.3.1 Epoch: 1 -Release: 4 +Release: 5 Summary: A modular Ruby webserver interface License: MIT and BSD URL: https://rack.github.io/ @@ -12,6 +12,8 @@ Source0: https://rubygems.org/downloads/%{gem_name}-%{version}.gem Patch6000: backport-CVE-2022-44570.patch Patch6001: backport-CVE-2022-44572.patch Patch6002: backport-CVE-2022-44571.patch +Patch6003: 2-2-multipart-dos.patch +Patch6004: 2-2-header-redos.patch BuildRequires: ruby(release) rubygems-devel ruby >= 2.2.2 memcached BuildArch: noarch @@ -41,6 +43,8 @@ Documentation for %{name}. %patch6000 -p1 %patch6001 -p1 %patch6002 -p1 +%patch6003 -p1 +%patch6004 -p1 %build gem build ../%{gem_name}-%{version}.gemspec @@ -98,6 +102,9 @@ popd %doc %{gem_instdir}/contrib %changelog +* Thu Dec 28 2023 sunwenhan - 1:2.2.3.1-5 +-fix CVE-2023-27539 CVE-2023-27530 + * Mon Dec 25 2023 wangweichao - 1:2.2.3.1-4 - fix CVE-2022-44571