Control: tags -1 patch Hi,
I've backported upstream's fixes for version 6.x. to version 5.7, along with a few additional lines that I believe are required to adequately fix this for 5.7. This seems to work as far as I can tell; upstream's test suite shows no regressions and the tests they added along with their fixes also pass. A patch is attached. Regards, Robin
From f8365784a8b5d9c3ef8ad0ce316bf056ea0eef5e Mon Sep 17 00:00:00 2001 From: Robin Gustafsson <ro...@rgson.se> Date: Sat, 1 May 2021 15:30:35 +0200 Subject: [PATCH] Security fix: Query Binding Exploitation Closes: #980899 CVE-2021-21263 --- ...01-6.x-Limit-expected-bindings-35865.patch | 98 +++++++++++++++++++ .../0002-Limit-expected-bindingx-v2.patch | 94 ++++++++++++++++++ ...hereDay-and-whereYear-to-clean-value.patch | 31 ++++++ ...it-bindings-for-having-between-tests.patch | 22 +++++ ...Clean-value-in-orWhereDay-Month-Year.patch | 42 ++++++++ debian/patches/series | 5 + 6 files changed, 292 insertions(+) create mode 100644 debian/patches/0001-6.x-Limit-expected-bindings-35865.patch create mode 100644 debian/patches/0002-Limit-expected-bindingx-v2.patch create mode 100644 debian/patches/0003-Update-whereDay-and-whereYear-to-clean-value.patch create mode 100644 debian/patches/0004-Add-limit-bindings-for-having-between-tests.patch create mode 100644 debian/patches/0005-Clean-value-in-orWhereDay-Month-Year.patch create mode 100644 debian/patches/series diff --git a/debian/patches/0001-6.x-Limit-expected-bindings-35865.patch b/debian/patches/0001-6.x-Limit-expected-bindings-35865.patch new file mode 100644 index 0000000000..a42ef10821 --- /dev/null +++ b/debian/patches/0001-6.x-Limit-expected-bindings-35865.patch @@ -0,0 +1,98 @@ +From: Taylor Otwell <tay...@laravel.com> +Date: Wed, 13 Jan 2021 07:35:45 -0600 +Subject: [6.x] Limit expected bindings (#35865) + +* limit expected bindings + +* limit more bindings + +Origin: https://github.com/laravel/framework/commit/d0954f4574f315f0c2e9e65e92cc74b80eadcac1 +--- + Query/Builder.php | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/Query/Builder.php b/Query/Builder.php +index 4fa3c6d..0812a70 100755 +--- a/Query/Builder.php ++++ b/Query/Builder.php +@@ -654,7 +654,7 @@ class Builder + ); + + if (! $value instanceof Expression) { +- $this->addBinding($value, 'where'); ++ $this->addBinding(is_array($value) ? head($value) : $value, 'where'); + } + + return $this; +@@ -1051,7 +1051,7 @@ class Builder + + $this->wheres[] = compact('type', 'column', 'values', 'boolean', 'not'); + +- $this->addBinding($this->cleanBindings($values), 'where'); ++ $this->addBinding(array_slice($this->cleanBindings($values), 0, 2), 'where'); + + return $this; + } +@@ -1119,6 +1119,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = is_array($value) ? head($value) : $value; ++ + if ($value instanceof DateTimeInterface) { + $value = $value->format('Y-m-d'); + } +@@ -1158,6 +1160,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = is_array($value) ? head($value) : $value; ++ + if ($value instanceof DateTimeInterface) { + $value = $value->format('H:i:s'); + } +@@ -1197,6 +1201,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = is_array($value) ? head($value) : $value; ++ + if ($value instanceof DateTimeInterface) { + $value = $value->format('d'); + } +@@ -1236,6 +1242,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = is_array($value) ? head($value) : $value; ++ + if ($value instanceof DateTimeInterface) { + $value = $value->format('m'); + } +@@ -1275,6 +1283,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = is_array($value) ? head($value) : $value; ++ + if ($value instanceof DateTimeInterface) { + $value = $value->format('Y'); + } +@@ -1581,7 +1591,7 @@ class Builder + $this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean'); + + if (! $value instanceof Expression) { +- $this->addBinding($value); ++ $this->addBinding((int) $value); + } + + return $this; +@@ -1714,7 +1724,7 @@ class Builder + $this->havings[] = compact('type', 'column', 'operator', 'value', 'boolean'); + + if (! $value instanceof Expression) { +- $this->addBinding($value, 'having'); ++ $this->addBinding(is_array($value) ? head($value) : $value, 'having'); + } + + return $this; diff --git a/debian/patches/0002-Limit-expected-bindingx-v2.patch b/debian/patches/0002-Limit-expected-bindingx-v2.patch new file mode 100644 index 0000000000..add0a09743 --- /dev/null +++ b/debian/patches/0002-Limit-expected-bindingx-v2.patch @@ -0,0 +1,94 @@ +From: Kane Cohen <kaneco...@gmail.com> +Date: Thu, 21 Jan 2021 08:44:52 +0000 +Subject: Limit expected bindingx v2. + +Origin: https://github.com/laravel/framework/commit/9d3752ca5f29c4cb1c0384fb01847820b6ac492c +--- + Query/Builder.php | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/Query/Builder.php b/Query/Builder.php +index 0812a70..f18ab57 100755 +--- a/Query/Builder.php ++++ b/Query/Builder.php +@@ -292,6 +292,17 @@ class Builder + return $this; + } + ++ /** ++ * Returns scalar type value from an unknown type of input. ++ * ++ * @param mixed $value ++ * @return mixed ++ */ ++ protected function scalarValue($value) ++ { ++ return is_array($value) ? head(Arr::flatten($value)) : $value; ++ } ++ + /** + * Creates a subquery and parse it. + * +@@ -654,7 +665,7 @@ class Builder + ); + + if (! $value instanceof Expression) { +- $this->addBinding(is_array($value) ? head($value) : $value, 'where'); ++ $this->addBinding($this->scalarValue($value), 'where'); + } + + return $this; +@@ -1051,7 +1062,7 @@ class Builder + + $this->wheres[] = compact('type', 'column', 'values', 'boolean', 'not'); + +- $this->addBinding(array_slice($this->cleanBindings($values), 0, 2), 'where'); ++ $this->addBinding(array_slice($this->cleanBindings(Arr::flatten($values)), 0, 2), 'where'); + + return $this; + } +@@ -1119,7 +1130,7 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + +- $value = is_array($value) ? head($value) : $value; ++ $value = $this->scalarValue($value); + + if ($value instanceof DateTimeInterface) { + $value = $value->format('Y-m-d'); +@@ -1160,7 +1171,7 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + +- $value = is_array($value) ? head($value) : $value; ++ $value = $this->scalarValue($value); + + if ($value instanceof DateTimeInterface) { + $value = $value->format('H:i:s'); +@@ -1242,7 +1253,7 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + +- $value = is_array($value) ? head($value) : $value; ++ $value = $this->scalarValue($value); + + if ($value instanceof DateTimeInterface) { + $value = $value->format('m'); +@@ -1591,7 +1602,7 @@ class Builder + $this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean'); + + if (! $value instanceof Expression) { +- $this->addBinding((int) $value); ++ $this->addBinding((int) $this->scalarValue($value)); + } + + return $this; +@@ -1724,7 +1735,7 @@ class Builder + $this->havings[] = compact('type', 'column', 'operator', 'value', 'boolean'); + + if (! $value instanceof Expression) { +- $this->addBinding(is_array($value) ? head($value) : $value, 'having'); ++ $this->addBinding($this->scalarValue($value), 'having'); + } + + return $this; diff --git a/debian/patches/0003-Update-whereDay-and-whereYear-to-clean-value.patch b/debian/patches/0003-Update-whereDay-and-whereYear-to-clean-value.patch new file mode 100644 index 0000000000..59aaa7aa47 --- /dev/null +++ b/debian/patches/0003-Update-whereDay-and-whereYear-to-clean-value.patch @@ -0,0 +1,31 @@ +From: Kane Cohen <kaneco...@gmail.com> +Date: Thu, 21 Jan 2021 10:48:50 +0000 +Subject: Update whereDay and whereYear to clean value. + +Origin: https://github.com/laravel/framework/commit/dbbb1c1c8a1fa0a51677b5a74fcfe0e2561ced91 +--- + Query/Builder.php | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Query/Builder.php b/Query/Builder.php +index f18ab57..79fa2e3 100755 +--- a/Query/Builder.php ++++ b/Query/Builder.php +@@ -1212,7 +1212,7 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + +- $value = is_array($value) ? head($value) : $value; ++ $value = $this->scalarValue($value); + + if ($value instanceof DateTimeInterface) { + $value = $value->format('d'); +@@ -1294,7 +1294,7 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + +- $value = is_array($value) ? head($value) : $value; ++ $value = $this->scalarValue($value); + + if ($value instanceof DateTimeInterface) { + $value = $value->format('Y'); diff --git a/debian/patches/0004-Add-limit-bindings-for-having-between-tests.patch b/debian/patches/0004-Add-limit-bindings-for-having-between-tests.patch new file mode 100644 index 0000000000..8470c1c633 --- /dev/null +++ b/debian/patches/0004-Add-limit-bindings-for-having-between-tests.patch @@ -0,0 +1,22 @@ +From: Kane Cohen <kaneco...@gmail.com> +Date: Thu, 21 Jan 2021 12:08:38 +0000 +Subject: Add limit bindings for having between + tests. + +Origin: https://github.com/laravel/framework/commit/c6b8168e6cbbe339fdc3af5ccdded545779965df +--- + Query/Builder.php | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Query/Builder.php b/Query/Builder.php +index 79fa2e3..9ad9c4c 100755 +--- a/Query/Builder.php ++++ b/Query/Builder.php +@@ -1773,7 +1773,7 @@ class Builder + + $this->havings[] = compact('type', 'column', 'values', 'boolean', 'not'); + +- $this->addBinding($this->cleanBindings($values), 'having'); ++ $this->addBinding(array_slice($this->cleanBindings(Arr::flatten($values)), 0, 2), 'having'); + + return $this; + } diff --git a/debian/patches/0005-Clean-value-in-orWhereDay-Month-Year.patch b/debian/patches/0005-Clean-value-in-orWhereDay-Month-Year.patch new file mode 100644 index 0000000000..b6d81de8e3 --- /dev/null +++ b/debian/patches/0005-Clean-value-in-orWhereDay-Month-Year.patch @@ -0,0 +1,42 @@ +From: Robin Gustafsson <ro...@rgson.se> +Date: Sat, 1 May 2021 15:52:36 +0200 +Subject: Clean value in orWhereDay/Month/Year + +In 6.x these methods call the whereDay/Month/Year methods where +the value is cleaned. In 5.x they don't, and so the value must +be cleaned here too. +--- + Query/Builder.php | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/Query/Builder.php b/Query/Builder.php +index 9ad9c4c..74222c7 100755 +--- a/Query/Builder.php ++++ b/Query/Builder.php +@@ -1235,6 +1235,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = $this->scalarValue($value); ++ + return $this->addDateBasedWhere('Day', $column, $operator, $value, 'or'); + } + +@@ -1276,6 +1278,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = $this->scalarValue($value); ++ + return $this->addDateBasedWhere('Month', $column, $operator, $value, 'or'); + } + +@@ -1317,6 +1321,8 @@ class Builder + $value, $operator, func_num_args() === 2 + ); + ++ $value = $this->scalarValue($value); ++ + return $this->addDateBasedWhere('Year', $column, $operator, $value, 'or'); + } + diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000000..ca17381904 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,5 @@ +0001-6.x-Limit-expected-bindings-35865.patch +0002-Limit-expected-bindingx-v2.patch +0003-Update-whereDay-and-whereYear-to-clean-value.patch +0004-Add-limit-bindings-for-having-between-tests.patch +0005-Clean-value-in-orWhereDay-Month-Year.patch -- 2.20.1