From eddda4d8fb6b6508e11196b14494ceac37b57339 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 10 Feb 2021 09:36:15 -0800 Subject: [PATCH] Fix possible DoS vector in PostgreSQL money type Carefully crafted input can cause a DoS via the regular expressions used for validating the money format in the PostgreSQL adapter. This patch fixes the regexp. Thanks to @dee-see from Hackerone for this patch! [CVE-2021-22880] --- .../connection_adapters/postgresql/oid/money.rb | 4 ++-- activerecord/test/cases/adapters/postgresql/money_test.rb | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb index 357493dfc0..3703e9a646 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb @@ -26,9 +26,9 @@ module ActiveRecord value = value.sub(/^\((.+)\)$/, '-\1') # (4) case value - when /^-?\D*[\d,]+\.\d{2}$/ # (1) + when /^-?\D*+[\d,]+\.\d{2}$/ # (1) value.gsub!(/[^-\d.]/, "") - when /^-?\D*[\d.]+,\d{2}$/ # (2) + when /^-?\D*+[\d.]+,\d{2}$/ # (2) value.gsub!(/[^-\d,]/, "").sub!(/,/, ".") end diff --git a/activerecord/test/cases/adapters/postgresql/money_test.rb b/activerecord/test/cases/adapters/postgresql/money_test.rb index b051a9efc4..da3643e57f 100644 --- a/activerecord/test/cases/adapters/postgresql/money_test.rb +++ b/activerecord/test/cases/adapters/postgresql/money_test.rb @@ -64,6 +64,14 @@ class PostgresqlMoneyTest < ActiveRecord::PostgreSQLTestCase assert_equal(-2.25, type.cast(+"(2.25)")) end + def test_money_regex_backtracking + type = PostgresqlMoney.type_for_attribute("wealth") + Timeout.timeout(0.1) do + assert_equal(0.0, type.cast("$" + "," * 100000 + ".11!")) + assert_equal(0.0, type.cast("$" + "." * 100000 + ",11!")) + end + end + def test_sum_with_type_cast @connection.execute("INSERT INTO postgresql_moneys (id, wealth) VALUES (1, '123.45'::money)")