CVE-2022-44566 CVE-2023-22794
(cherry picked from commit c2f061a46882e2e45ab9157f5596aed7e9d1efca)
This commit is contained in:
parent
62956e1133
commit
26a7f3c058
133
CVE-2022-44566.patch
Normal file
133
CVE-2022-44566.patch
Normal file
@ -0,0 +1,133 @@
|
||||
From 82bcdc011e2ff674e7dd8fd8cee3a831c908d29b Mon Sep 17 00:00:00 2001
|
||||
From: Zack Deveau <zack.ref@gmail.com>
|
||||
Date: Mon, 21 Nov 2022 17:11:31 -0500
|
||||
Subject: [PATCH] Added integer width check to PostgreSQL::Quoting
|
||||
|
||||
Given a value outside the range for a 64bit signed integer type
|
||||
PostgreSQL will treat the column type as numeric.
|
||||
Comparing integer values against numeric values can result
|
||||
in a slow sequential scan.
|
||||
|
||||
This behavior is configurable via
|
||||
ActiveRecord.raise_int_wider_than_64bit which defaults to true.
|
||||
|
||||
[CVE-2022-44566]
|
||||
---
|
||||
activerecord-7.0.4/lib/active_record.rb | 8 ++++++
|
||||
.../connection_adapters/postgresql/quoting.rb | 26 +++++++++++++++++
|
||||
.../cases/adapters/postgresql/quoting_test.rb | 28 +++++++++++++++++++
|
||||
3 files changed, 85 insertions(+)
|
||||
|
||||
diff --git a/activerecord-7.0.4/lib/active_record.rb b/activerecord-7.0.4/lib/active_record.rb
|
||||
index d553fe5c7c..4f6e5493e7 100644
|
||||
--- a/activerecord-7.0.4/lib/active_record.rb
|
||||
+++ b/activerecord-7.0.4/lib/active_record.rb
|
||||
@@ -347,6 +347,14 @@ def self.global_executor_concurrency # :nodoc:
|
||||
singleton_class.attr_accessor :use_yaml_unsafe_load
|
||||
self.use_yaml_unsafe_load = false
|
||||
|
||||
+ ##
|
||||
+ # :singleton-method:
|
||||
+ # Application configurable boolean that denotes whether or not to raise
|
||||
+ # an exception when the PostgreSQLAdapter is provided with an integer that
|
||||
+ # is wider than signed 64bit representation
|
||||
+ singleton_class.attr_accessor :raise_int_wider_than_64bit
|
||||
+ self.raise_int_wider_than_64bit = true
|
||||
+
|
||||
##
|
||||
# :singleton-method:
|
||||
# Application configurable array that provides additional permitted classes
|
||||
diff --git a/activerecord-7.0.4/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord-7.0.4/lib/active_record/connection_adapters/postgresql/quoting.rb
|
||||
index 0d1cd8b02d..d5591dbe00 100644
|
||||
--- a/activerecord-7.0.4/lib/active_record/connection_adapters/postgresql/quoting.rb
|
||||
+++ b/activerecord-7.0.4/lib/active_record/connection_adapters/postgresql/quoting.rb
|
||||
@@ -4,6 +4,12 @@
|
||||
module ConnectionAdapters
|
||||
module PostgreSQL
|
||||
module Quoting
|
||||
+ class IntegerOutOf64BitRange < StandardError
|
||||
+ def initialize(msg)
|
||||
+ super(msg)
|
||||
+ end
|
||||
+ end
|
||||
+
|
||||
# Escapes binary strings for bytea input to the database.
|
||||
def escape_bytea(value)
|
||||
@connection.escape_bytea(value) if value
|
||||
@@ -16,7 +22,27 @@ def unescape_bytea(value)
|
||||
@connection.unescape_bytea(value) if value
|
||||
end
|
||||
|
||||
+ def check_int_in_range(value)
|
||||
+ if value.to_int > 9223372036854775807 || value.to_int < -9223372036854775808
|
||||
+ exception = <<~ERROR
|
||||
+ Provided value outside of the range of a signed 64bit integer.
|
||||
+
|
||||
+ PostgreSQL will treat the column type in question as a numeric.
|
||||
+ This may result in a slow sequential scan due to a comparison
|
||||
+ being performed between an integer or bigint value and a numeric value.
|
||||
+
|
||||
+ To allow for this potentially unwanted behavior, set
|
||||
+ ActiveRecord.raise_int_wider_than_64bit to false.
|
||||
+ ERROR
|
||||
+ raise IntegerOutOf64BitRange.new exception
|
||||
+ end
|
||||
+ end
|
||||
+
|
||||
def quote(value) # :nodoc:
|
||||
+ if ActiveRecord.raise_int_wider_than_64bit && value.is_a?(Integer)
|
||||
+ check_int_in_range(value)
|
||||
+ end
|
||||
+
|
||||
case value
|
||||
when OID::Xml::Data
|
||||
"xml '#{quote_string(value.to_s)}'"
|
||||
diff --git a/test/cases/adapters/postgresql/quoting_test.rb b/test/cases/adapters/postgresql/quoting_test.rb
|
||||
index d571355a9c..7e01defd96 100644
|
||||
--- a/test/cases/adapters/postgresql/quoting_test.rb
|
||||
+++ b/test/cases/adapters/postgresql/quoting_test.rb
|
||||
@@ -8,6 +8,7 @@
|
||||
class QuotingTest < ActiveRecord::PostgreSQLTestCase
|
||||
def setup
|
||||
@conn = ActiveRecord::Base.connection
|
||||
+ @raise_int_wider_than_64bit = ActiveRecord.raise_int_wider_than_64bit
|
||||
end
|
||||
|
||||
def test_type_cast_true
|
||||
@@ -44,6 +45,33 @@ def test_quote_table_name_with_spaces
|
||||
value = "user posts"
|
||||
assert_equal "\"user posts\"", @conn.quote_table_name(value)
|
||||
end
|
||||
+
|
||||
+ def test_raise_when_int_is_wider_than_64bit
|
||||
+ value = 9223372036854775807 + 1
|
||||
+ assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
|
||||
+ @conn.quote(value)
|
||||
+ end
|
||||
+
|
||||
+ value = -9223372036854775808 - 1
|
||||
+ assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
|
||||
+ @conn.quote(value)
|
||||
+ end
|
||||
+ end
|
||||
+
|
||||
+ def test_do_not_raise_when_int_is_not_wider_than_64bit
|
||||
+ value = 9223372036854775807
|
||||
+ assert_equal "9223372036854775807", @conn.quote(value)
|
||||
+
|
||||
+ value = -9223372036854775808
|
||||
+ assert_equal "-9223372036854775808", @conn.quote(value)
|
||||
+ end
|
||||
+
|
||||
+ def test_do_not_raise_when_raise_int_wider_than_64bit_is_false
|
||||
+ ActiveRecord.raise_int_wider_than_64bit = false
|
||||
+ value = 9223372036854775807 + 1
|
||||
+ assert_equal "9223372036854775808", @conn.quote(value)
|
||||
+ ActiveRecord.raise_int_wider_than_64bit = @raise_int_wider_than_64bit
|
||||
+ end
|
||||
end
|
||||
end
|
||||
end
|
||||
--
|
||||
2.35.1
|
||||
|
||||
171
CVE-2023-22794.patch
Normal file
171
CVE-2023-22794.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From d7aba06953f9fa789c411676b941d20df8ef73de Mon Sep 17 00:00:00 2001
|
||||
From: John Hawthorn <john@hawthorn.email>
|
||||
Date: Tue, 6 Sep 2022 15:49:26 -0700
|
||||
Subject: [PATCH] Make sanitize_as_sql_comment more strict
|
||||
|
||||
Though this method was likely never meant to take user input, it was
|
||||
attempting sanitization. That sanitization could be bypassed with
|
||||
carefully crafted input.
|
||||
|
||||
This commit makes the sanitization more robust by replacing any
|
||||
occurrances of "/*" or "*/" with "/ *" or "* /". It also performs a
|
||||
first pass to remove one surrounding comment to avoid compatibility
|
||||
issues for users relying on the existing removal.
|
||||
|
||||
This also clarifies in the documentation of annotate that it should not
|
||||
be provided user input.
|
||||
|
||||
[CVE-2023-22794]
|
||||
---
|
||||
.../connection_adapters/abstract/quoting.rb | 11 ++++++++++-
|
||||
activerecord-7.0.4/lib/active_record/query_logs.rb | 13 ++++++++++++-
|
||||
.../lib/active_record/relation/query_methods.rb | 2 ++
|
||||
activerecord-7.0.4/test/cases/annotate_test.rb | 11 ++++++++---
|
||||
activerecord-7.0.4/test/cases/query_logs_test.rb | 5 +++--
|
||||
activerecord-7.0.4/test/cases/relation_test.rb | 10 +++-------
|
||||
6 files changed, 38 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/activerecord-7.0.4/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord-7.0.4/lib/active_record/connection_adapters/abstract/quoting.rb
|
||||
index dda3145bdd..3b7819eb56 100644
|
||||
--- a/activerecord-7.0.4/lib/active_record/connection_adapters/abstract/quoting.rb
|
||||
+++ b/activerecord-7.0.4/lib/active_record/connection_adapters/abstract/quoting.rb
|
||||
@@ -146,7 +146,16 @@ def quoted_binary(value) # :nodoc:
|
||||
end
|
||||
|
||||
def sanitize_as_sql_comment(value) # :nodoc:
|
||||
- value.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "")
|
||||
+ # Sanitize a string to appear within a SQL comment
|
||||
+ # For compatibility, this also surrounding "/*+", "/*", and "*/"
|
||||
+ # charcacters, possibly with single surrounding space.
|
||||
+ # Then follows that by replacing any internal "*/" or "/ *" with
|
||||
+ # "* /" or "/ *"
|
||||
+ comment = value.to_s.dup
|
||||
+ comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
|
||||
+ comment.gsub!("*/", "* /")
|
||||
+ comment.gsub!("/*", "/ *")
|
||||
+ comment
|
||||
end
|
||||
|
||||
def column_name_matcher # :nodoc:
|
||||
diff --git a/activerecord-7.0.4/lib/active_record/query_logs.rb b/activerecord-7.0.4/lib/active_record/query_logs.rb
|
||||
index f116a154dd..2fd6ca3640 100644
|
||||
--- a/activerecord-7.0.4/lib/active_record/query_logs.rb
|
||||
+++ b/activerecord-7.0.4/lib/active_record/query_logs.rb
|
||||
@@ -33,6 +33,8 @@
|
||||
# want to add to the comment. Dynamic content can be created by setting a proc or lambda value in a hash,
|
||||
# and can reference any value stored in the +context+ object.
|
||||
#
|
||||
+ # Escaping is performed on the string returned, however untrusted user input should not be used.
|
||||
+ #
|
||||
# Example:
|
||||
#
|
||||
# tags = [
|
||||
@@ -109,7 +111,16 @@ def uncached_comment
|
||||
end
|
||||
|
||||
def escape_sql_comment(content)
|
||||
- content.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "")
|
||||
+ # Sanitize a string to appear within a SQL comment
|
||||
+ # For compatibility, this also surrounding "/*+", "/*", and "*/"
|
||||
+ # charcacters, possibly with single surrounding space.
|
||||
+ # Then follows that by replacing any internal "*/" or "/ *" with
|
||||
+ # "* /" or "/ *"
|
||||
+ comment = content.to_s.dup
|
||||
+ comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
|
||||
+ comment.gsub!("*/", "* /")
|
||||
+ comment.gsub!("/*", "/ *")
|
||||
+ comment
|
||||
end
|
||||
|
||||
def tag_content
|
||||
diff --git a/activerecord-7.0.4/lib/active_record/relation/query_methods.rb b/activerecord-7.0.4/lib/active_record/relation/query_methods.rb
|
||||
index 25136331f9..cf7c524291 100644
|
||||
--- a/activerecord-7.0.4/lib/active_record/relation/query_methods.rb
|
||||
+++ b/activerecord-7.0.4/lib/active_record/relation/query_methods.rb
|
||||
@@ -1216,6 +1216,8 @@ def skip_preloading! # :nodoc:
|
||||
# # SELECT "users"."name" FROM "users" /* selecting */ /* user */ /* names */
|
||||
#
|
||||
# The SQL block comment delimiters, "/*" and "*/", will be added automatically.
|
||||
+ #
|
||||
+ # Some escaping is performed, however untrusted user input should not be used.
|
||||
def annotate(*args)
|
||||
check_if_method_has_arguments!(__callee__, args)
|
||||
spawn.annotate!(*args)
|
||||
diff --git a/test/cases/annotate_test.rb b/test/cases/annotate_test.rb
|
||||
index b0802ca559..ed1d846178 100644
|
||||
--- a/test/cases/annotate_test.rb
|
||||
+++ b/test/cases/annotate_test.rb
|
||||
@@ -18,17 +18,22 @@ def test_annotate_wraps_content_in_an_inline_comment
|
||||
def test_annotate_is_sanitized
|
||||
quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
|
||||
|
||||
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
|
||||
+ assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/}i) do
|
||||
posts = Post.select(:id).annotate("*/foo/*")
|
||||
assert posts.first
|
||||
end
|
||||
|
||||
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
|
||||
+ assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \*\* //foo// \*\* \*/}i) do
|
||||
posts = Post.select(:id).annotate("**//foo//**")
|
||||
assert posts.first
|
||||
end
|
||||
|
||||
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/ /\* bar \*/}i) do
|
||||
+ assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* \* //foo// \* \* \*/}i) do
|
||||
+ posts = Post.select(:id).annotate("* *//foo//* *")
|
||||
+ assert posts.first
|
||||
+ end
|
||||
+
|
||||
+ assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/ /\* \* /bar \*/}i) do
|
||||
posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
|
||||
assert posts.first
|
||||
end
|
||||
diff --git a/test/cases/query_logs_test.rb b/test/cases/query_logs_test.rb
|
||||
index 05207f17e3..09ca530417 100644
|
||||
--- a/test/cases/query_logs_test.rb
|
||||
+++ b/test/cases/query_logs_test.rb
|
||||
@@ -42,8 +42,9 @@ def test_escaping_good_comment
|
||||
end
|
||||
|
||||
def test_escaping_bad_comments
|
||||
- assert_equal "; DROP TABLE USERS;", ActiveRecord::QueryLogs.send(:escape_sql_comment, "*/; DROP TABLE USERS;/*")
|
||||
- assert_equal "; DROP TABLE USERS;", ActiveRecord::QueryLogs.send(:escape_sql_comment, "**//; DROP TABLE USERS;/*")
|
||||
+ assert_equal "* /; DROP TABLE USERS;/ *", ActiveRecord::QueryLogs.send(:escape_sql_comment, "*/; DROP TABLE USERS;/*")
|
||||
+ assert_equal "** //; DROP TABLE USERS;/ *", ActiveRecord::QueryLogs.send(:escape_sql_comment, "**//; DROP TABLE USERS;/*")
|
||||
+ assert_equal "* * //; DROP TABLE USERS;// * *", ActiveRecord::QueryLogs.send(:escape_sql_comment, "* *//; DROP TABLE USERS;//* *")
|
||||
end
|
||||
|
||||
def test_basic_commenting
|
||||
diff --git a/test/cases/relation_test.rb b/test/cases/relation_test.rb
|
||||
index 1da95bd3ae..0aed326678 100644
|
||||
--- a/test/cases/relation_test.rb
|
||||
+++ b/test/cases/relation_test.rb
|
||||
@@ -345,7 +345,7 @@ def test_relation_with_annotation_chains_sql_comments
|
||||
|
||||
def test_relation_with_annotation_filters_sql_comment_delimiters
|
||||
post_with_annotation = Post.where(id: 1).annotate("**//foo//**")
|
||||
- assert_match %r{= 1 /\* foo \*/}, post_with_annotation.to_sql
|
||||
+ assert_includes post_with_annotation.to_sql, "= 1 /* ** //foo// ** */"
|
||||
end
|
||||
|
||||
def test_relation_with_annotation_includes_comment_in_count_query
|
||||
@@ -367,13 +367,9 @@ def test_relation_without_annotation_does_not_include_an_empty_comment
|
||||
|
||||
def test_relation_with_optimizer_hints_filters_sql_comment_delimiters
|
||||
post_with_hint = Post.where(id: 1).optimizer_hints("**//BADHINT//**")
|
||||
- assert_match %r{BADHINT}, post_with_hint.to_sql
|
||||
- assert_no_match %r{\*/BADHINT}, post_with_hint.to_sql
|
||||
- assert_no_match %r{\*//BADHINT}, post_with_hint.to_sql
|
||||
- assert_no_match %r{BADHINT/\*}, post_with_hint.to_sql
|
||||
- assert_no_match %r{BADHINT//\*}, post_with_hint.to_sql
|
||||
+ assert_includes post_with_hint.to_sql, "/*+ ** //BADHINT// ** */"
|
||||
post_with_hint = Post.where(id: 1).optimizer_hints("/*+ BADHINT */")
|
||||
- assert_match %r{/\*\+ BADHINT \*/}, post_with_hint.to_sql
|
||||
+ assert_includes post_with_hint.to_sql, "/*+ BADHINT */"
|
||||
end
|
||||
|
||||
def test_does_not_duplicate_optimizer_hints_on_merge
|
||||
--
|
||||
2.35.1
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
Name: rubygem-%{gem_name}
|
||||
Epoch: 1
|
||||
Version: 7.0.4
|
||||
Release: 1
|
||||
Release: 2
|
||||
Summary: Object-relational mapper framework (part of Rails)
|
||||
License: MIT
|
||||
URL: http://rubyonrails.org
|
||||
@ -24,7 +24,8 @@ Patch0: rubygem-activerecord-7.0.2.3-Fix-assert_called_with-with-em
|
||||
Patch1: rubygem-activerecord-7.0.2.3-Remove-the-multi-call-form-of-assert_called_with.patch
|
||||
# https://github.com/rails/rails/pull/45370
|
||||
Patch2: rubygem-activerecord-7.0.2.3-Fix-tests-for-minitest-5.16.patch
|
||||
|
||||
Patch3: CVE-2022-44566.patch
|
||||
Patch4: CVE-2023-22794.patch
|
||||
Suggests: %{_bindir}/sqlite3
|
||||
BuildRequires: rubygems-devel rubygem(bcrypt) rubygem(activesupport) = %{version}
|
||||
BuildRequires: rubygem(activemodel) = %{version} rubygem(builder) rubygem(sqlite3)
|
||||
@ -52,6 +53,8 @@ Documentation for %{name}.
|
||||
pushd %{_builddir}
|
||||
%patch1 -p2
|
||||
%patch2 -p2
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
popd
|
||||
%build
|
||||
gem build ../%{gem_name}-%{version}.gemspec
|
||||
@ -104,6 +107,9 @@ popd
|
||||
%{gem_instdir}/examples
|
||||
|
||||
%changelog
|
||||
* Wed Feb 22 2023 wushaozheng <wushaozheng@ncti-gba.cn> - 1:7.0.4-2
|
||||
- fix CVE-2022-44566 CVE-2023-22794
|
||||
|
||||
* Thu Jan 19 2023 yanxiaobing <yanxiaobing@huawei.com> - 1:7.0.4-1
|
||||
- Upgrade to version 7.0.4
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user