diff options
author | Remi Collet <remi@remirepo.net> | 2023-02-14 16:48:17 +0100 |
---|---|---|
committer | Remi Collet <remi@php.net> | 2023-02-14 16:48:17 +0100 |
commit | 0afe7affd1c4b8948654e006e64ec07f77098e03 (patch) | |
tree | 35217c709b96bed65de2247d0ebb9b4a4ac63b38 | |
parent | cd26a77467429c662fa2f8b94379ea28787924bf (diff) |
fix #81744: Password_verify() always return true with some hash
CVE-2023-0567
fix #81746: 1-byte array overrun in common path resolve code
CVE-2023-0568
fix DOS vulnerability when parsing multipart request body
CVE-2023-0662
-rw-r--r-- | failed.txt | 16 | ||||
-rw-r--r-- | php-bug81744.patch | 190 | ||||
-rw-r--r-- | php-bug81746.patch | 100 | ||||
-rw-r--r-- | php-cve-2023-0662.patch | 148 | ||||
-rw-r--r-- | php.spec | 16 |
5 files changed, 459 insertions, 11 deletions
@@ -1,18 +1,15 @@ -===== 7.2.34-12 (2022-09-29) +===== 7.2.34-16 (2023-02-14) $ grep -ar 'Tests failed' /var/lib/mock/*/build.log /var/lib/mock/scl72el7x/build.log:Tests failed : 0 -/var/lib/mock/scl72el8x/build.log:Tests failed : 18 -/var/lib/mock/scl72fc35x/build.log:Tests failed : 18 +/var/lib/mock/scl72el8x/build.log:Tests failed : 20 -el8x - 4 Bug #48097 (date_timezone_set function produces wrong datetime result) [ext/date/tests/bug48097.phpt] -el8x, fc33x, fc34x: - 3 buildroot issue with strict openssl policy (fixed in 7.4) -fc33x, fc34x, fc35x - 4 Bug #33415 [2] (Possibly invalid non-one-hour DST or timezone shifts) [ext/date/tests/bug33415-2.phpt] +el7x: + 3 ext/openssl/tests/openssl_x509_checkpurpose_basic.phpt +el8x: + 3 buildroot issue with strict openssl policy (fixed in 7.4) and tzdata (1) proc_open give erratic test results :( @@ -20,4 +17,3 @@ fc33x, fc34x, fc35x (3) known issue (4) tzdata related (5) need investigation - diff --git a/php-bug81744.patch b/php-bug81744.patch new file mode 100644 index 0000000..2864136 --- /dev/null +++ b/php-bug81744.patch @@ -0,0 +1,190 @@ +From 77e6dd89b92c3c7b3191e53508b1cd1744a89208 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be> +Date: Mon, 23 Jan 2023 21:15:24 +0100 +Subject: [PATCH 1/8] crypt: Fix validation of malformed BCrypt hashes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +PHP’s implementation of crypt_blowfish differs from the upstream Openwall +version by adding a “PHP Hack”, which allows one to cut short the BCrypt salt +by including a `$` character within the characters that represent the salt. + +Hashes that are affected by the “PHP Hack” may erroneously validate any +password as valid when used with `password_verify` and when comparing the +return value of `crypt()` against the input. + +The PHP Hack exists since the first version of PHP’s own crypt_blowfish +implementation that was added in 1e820eca02dcf322b41fd2fe4ed2a6b8309f8ab5. + +No clear reason is given for the PHP Hack’s existence. This commit removes it, +because BCrypt hashes containing a `$` character in their salt are not valid +BCrypt hashes. + +(cherry picked from commit c840f71524067aa474c00c3eacfb83bd860bfc8a) +(cherry picked from commit 7437aaae38cf4b3357e7580f9e22fd4a403b6c23) +--- + ext/standard/crypt_blowfish.c | 8 -- + .../tests/crypt/bcrypt_salt_dollar.phpt | 82 +++++++++++++++++++ + 2 files changed, 82 insertions(+), 8 deletions(-) + create mode 100644 ext/standard/tests/crypt/bcrypt_salt_dollar.phpt + +diff --git a/ext/standard/crypt_blowfish.c b/ext/standard/crypt_blowfish.c +index 5cf306715f..e923b55ed0 100644 +--- a/ext/standard/crypt_blowfish.c ++++ b/ext/standard/crypt_blowfish.c +@@ -377,7 +377,6 @@ static unsigned char BF_atoi64[0x60] = { + #define BF_safe_atoi64(dst, src) \ + { \ + tmp = (unsigned char)(src); \ +- if (tmp == '$') break; /* PHP hack */ \ + if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ + tmp = BF_atoi64[tmp]; \ + if (tmp > 63) return -1; \ +@@ -405,13 +404,6 @@ static int BF_decode(BF_word *dst, const char *src, int size) + *dptr++ = ((c3 & 0x03) << 6) | c4; + } while (dptr < end); + +- if (end - dptr == size) { +- return -1; +- } +- +- while (dptr < end) /* PHP hack */ +- *dptr++ = 0; +- + return 0; + } + +diff --git a/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt +new file mode 100644 +index 0000000000..32e335f4b0 +--- /dev/null ++++ b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt +@@ -0,0 +1,82 @@ ++--TEST-- ++bcrypt correctly rejects salts containing $ ++--FILE-- ++<?php ++for ($i = 0; $i < 23; $i++) { ++ $salt = '$2y$04$' . str_repeat('0', $i) . '$'; ++ $result = crypt("foo", $salt); ++ var_dump($salt); ++ var_dump($result); ++ var_dump($result === $salt); ++} ++?> ++--EXPECT-- ++string(8) "$2y$04$$" ++string(2) "*0" ++bool(false) ++string(9) "$2y$04$0$" ++string(2) "*0" ++bool(false) ++string(10) "$2y$04$00$" ++string(2) "*0" ++bool(false) ++string(11) "$2y$04$000$" ++string(2) "*0" ++bool(false) ++string(12) "$2y$04$0000$" ++string(2) "*0" ++bool(false) ++string(13) "$2y$04$00000$" ++string(2) "*0" ++bool(false) ++string(14) "$2y$04$000000$" ++string(2) "*0" ++bool(false) ++string(15) "$2y$04$0000000$" ++string(2) "*0" ++bool(false) ++string(16) "$2y$04$00000000$" ++string(2) "*0" ++bool(false) ++string(17) "$2y$04$000000000$" ++string(2) "*0" ++bool(false) ++string(18) "$2y$04$0000000000$" ++string(2) "*0" ++bool(false) ++string(19) "$2y$04$00000000000$" ++string(2) "*0" ++bool(false) ++string(20) "$2y$04$000000000000$" ++string(2) "*0" ++bool(false) ++string(21) "$2y$04$0000000000000$" ++string(2) "*0" ++bool(false) ++string(22) "$2y$04$00000000000000$" ++string(2) "*0" ++bool(false) ++string(23) "$2y$04$000000000000000$" ++string(2) "*0" ++bool(false) ++string(24) "$2y$04$0000000000000000$" ++string(2) "*0" ++bool(false) ++string(25) "$2y$04$00000000000000000$" ++string(2) "*0" ++bool(false) ++string(26) "$2y$04$000000000000000000$" ++string(2) "*0" ++bool(false) ++string(27) "$2y$04$0000000000000000000$" ++string(2) "*0" ++bool(false) ++string(28) "$2y$04$00000000000000000000$" ++string(2) "*0" ++bool(false) ++string(29) "$2y$04$000000000000000000000$" ++string(2) "*0" ++bool(false) ++string(30) "$2y$04$0000000000000000000000$" ++string(60) "$2y$04$000000000000000000000u2a2UpVexIt9k3FMJeAVr3c04F5tcI8K" ++bool(false) +-- +2.39.1 + +From c57400002961b6df74960c52777ad0fb3dbeabea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be> +Date: Mon, 23 Jan 2023 22:13:57 +0100 +Subject: [PATCH 2/8] crypt: Fix possible buffer overread in php_crypt() + +(cherry picked from commit a92acbad873a05470af1a47cb785a18eadd827b5) +(cherry picked from commit ed0281b588a6840cb95f3134a4e68847a3be5bb7) +--- + ext/standard/crypt.c | 1 + + ext/standard/tests/password/password_bcrypt_short.phpt | 8 ++++++++ + 2 files changed, 9 insertions(+) + create mode 100644 ext/standard/tests/password/password_bcrypt_short.phpt + +diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c +index e873ca7946..c391cfd3f6 100644 +--- a/ext/standard/crypt.c ++++ b/ext/standard/crypt.c +@@ -156,6 +156,7 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch + } else if ( + salt[0] == '$' && + salt[1] == '2' && ++ salt[2] != 0 && + salt[3] == '$') { + char output[PHP_MAX_SALT_LEN + 1]; + +diff --git a/ext/standard/tests/password/password_bcrypt_short.phpt b/ext/standard/tests/password/password_bcrypt_short.phpt +new file mode 100644 +index 0000000000..085bc8a239 +--- /dev/null ++++ b/ext/standard/tests/password/password_bcrypt_short.phpt +@@ -0,0 +1,8 @@ ++--TEST-- ++Test that password_hash() does not overread buffers when a short hash is passed ++--FILE-- ++<?php ++var_dump(password_verify("foo", '$2')); ++?> ++--EXPECT-- ++bool(false) +-- +2.39.1 + diff --git a/php-bug81746.patch b/php-bug81746.patch new file mode 100644 index 0000000..c654709 --- /dev/null +++ b/php-bug81746.patch @@ -0,0 +1,100 @@ +From 3640e9897928d5b5607270c20593a0c04a455e1e Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Fri, 27 Jan 2023 19:28:27 +0100 +Subject: [PATCH 3/8] Fix array overrun when appending slash to paths + +Fix it by extending the array sizes by one character. As the input is +limited to the maximum path length, there will always be place to append +the slash. As the php_check_specific_open_basedir() simply uses the +strings to compare against each other, no new failures related to too +long paths are introduced. +We'll let the DOM and XML case handle a potentially too long path in the +library code. + +(cherry picked from commit ec10b28d64decbc54aa1e585dce580f0bd7a5953) +(cherry picked from commit 887cd0710ad856a0d22c329b6ea6c71ebd8621ae) +--- + ext/dom/document.c | 2 +- + ext/xmlreader/php_xmlreader.c | 2 +- + main/fopen_wrappers.c | 6 +++--- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/ext/dom/document.c b/ext/dom/document.c +index 11ef4aa818..c212faa695 100644 +--- a/ext/dom/document.c ++++ b/ext/dom/document.c +@@ -1359,7 +1359,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so + int validate, recover, resolve_externals, keep_blanks, substitute_ent; + int resolved_path_len; + int old_error_reporting = 0; +- char *directory=NULL, resolved_path[MAXPATHLEN]; ++ char *directory=NULL, resolved_path[MAXPATHLEN + 1]; + + if (id != NULL) { + intern = Z_DOMOBJ_P(id); +diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c +index 6c1da2761d..0f2b62ae20 100644 +--- a/ext/xmlreader/php_xmlreader.c ++++ b/ext/xmlreader/php_xmlreader.c +@@ -1040,7 +1040,7 @@ PHP_METHOD(xmlreader, XML) + xmlreader_object *intern = NULL; + char *source, *uri = NULL, *encoding = NULL; + int resolved_path_len, ret = 0; +- char *directory=NULL, resolved_path[MAXPATHLEN]; ++ char *directory=NULL, resolved_path[MAXPATHLEN + 1]; + xmlParserInputBufferPtr inputbfr; + xmlTextReaderPtr reader; + +diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c +index 520edfadbb..33047bb160 100644 +--- a/main/fopen_wrappers.c ++++ b/main/fopen_wrappers.c +@@ -135,10 +135,10 @@ PHPAPI ZEND_INI_MH(OnUpdateBaseDir) + */ + PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path) + { +- char resolved_name[MAXPATHLEN]; +- char resolved_basedir[MAXPATHLEN]; ++ char resolved_name[MAXPATHLEN + 1]; ++ char resolved_basedir[MAXPATHLEN + 1]; + char local_open_basedir[MAXPATHLEN]; +- char path_tmp[MAXPATHLEN]; ++ char path_tmp[MAXPATHLEN + 1]; + char *path_file; + size_t resolved_basedir_len; + size_t resolved_name_len; +-- +2.39.1 + +From 2b9c9a8cb00914c08e34ee242d4aa3ba4aa74ef4 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Mon, 13 Feb 2023 11:46:47 +0100 +Subject: [PATCH 4/8] NEWS + +(cherry picked from commit 614468ce4056c0ef93aae09532dcffdf65b594b5) +--- + NEWS | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/NEWS b/NEWS +index 1c00ef6357..ad57c5ccd5 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,14 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.28 ++ ++- Core: ++ . Fixed bug #81744 (Password_verify() always return true with some hash). ++ (CVE-2023-0567). (Tim Düsterhus) ++ . Fixed bug #81746 (1-byte array overrun in common path resolve code). ++ (CVE-2023-0568). (Niels Dossche) ++ + Backported from 8.0.27 + + - PDO/SQLite: +-- +2.39.1 + diff --git a/php-cve-2023-0662.patch b/php-cve-2023-0662.patch new file mode 100644 index 0000000..07361d1 --- /dev/null +++ b/php-cve-2023-0662.patch @@ -0,0 +1,148 @@ +From 1548e88ea16f68d15a71040c7fb6bff3874c5e32 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Thu, 19 Jan 2023 14:11:18 +0000 +Subject: [PATCH 5/8] Fix repeated warning for file uploads limit exceeding + +(cherry picked from commit 3a2fdef1ae38881110006616ee1f0534b082ca45) +--- + main/rfc1867.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/main/rfc1867.c b/main/rfc1867.c +index 27718e72a4..3f7a0c76f9 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -932,7 +932,10 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + skip_upload = 1; + } else if (upload_cnt <= 0) { + skip_upload = 1; +- sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); ++ if (upload_cnt == 0) { ++ --upload_cnt; ++ sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); ++ } + } + + /* Return with an error if the posted data is garbled */ +-- +2.39.1 + +From 7d196fe1295491e624edf263525148c8c3bfd902 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Thu, 19 Jan 2023 14:31:25 +0000 +Subject: [PATCH 6/8] Introduce max_multipart_body_parts INI + +This fixes GHSA-54hq-v5wp-fqgv DOS vulnerabality by limitting number of +parsed multipart body parts as currently all parts were always parsed. + +(cherry picked from commit 8ec78d28d20c82c75c4747f44c52601cfdb22516) +--- + main/main.c | 1 + + main/rfc1867.c | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/main/main.c b/main/main.c +index a3fc980b17..0cfdb91368 100644 +--- a/main/main.c ++++ b/main/main.c +@@ -621,6 +621,7 @@ PHP_INI_BEGIN() + PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL) + PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL) + PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) ++ PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) + + STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals) + STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals) +diff --git a/main/rfc1867.c b/main/rfc1867.c +index 3f7a0c76f9..14813a300c 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -704,6 +704,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + void *event_extra_data = NULL; + unsigned int llen = 0; + int upload_cnt = INI_INT("max_file_uploads"); ++ int body_parts_cnt = INI_INT("max_multipart_body_parts"); + const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(); + php_rfc1867_getword_t getword; + php_rfc1867_getword_conf_t getword_conf; +@@ -725,6 +726,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + return; + } + ++ if (body_parts_cnt < 0) { ++ body_parts_cnt = PG(max_input_vars) + upload_cnt; ++ } ++ int body_parts_limit = body_parts_cnt; ++ + /* Get the boundary */ + boundary = strstr(content_type_dup, "boundary"); + if (!boundary) { +@@ -809,6 +815,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + char *pair = NULL; + int end = 0; + ++ if (--body_parts_cnt < 0) { ++ php_error_docref(NULL, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit); ++ goto fileupload_done; ++ } ++ + while (isspace(*cd)) { + ++cd; + } +-- +2.39.1 + +From 7900df2bfa37eaf0217fd2d62f3418b0be096cba Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 14 Feb 2023 09:14:47 +0100 +Subject: [PATCH 7/8] NEWS + +(cherry picked from commit 472db3ee3a00ac00d36019eee0b3b7362334481c) +--- + NEWS | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/NEWS b/NEWS +index ad57c5ccd5..e59c43300a 100644 +--- a/NEWS ++++ b/NEWS +@@ -9,6 +9,10 @@ Backported from 8.0.28 + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) + ++- FPM: ++ . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart ++ request body). (CVE-2023-0662) (Jakub Zelenka) ++ + Backported from 8.0.27 + + - PDO/SQLite: +-- +2.39.1 + +From 27d1f29635717f619267b5e2ebf87ec43faa18f0 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 14 Feb 2023 11:47:22 +0100 +Subject: [PATCH 8/8] fix NEWS, not FPM specific + +(cherry picked from commit c04f310440a906fc4ca885f4ecf6e3e4cd36edc7) +--- + NEWS | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/NEWS b/NEWS +index e59c43300a..47e9f89a64 100644 +--- a/NEWS ++++ b/NEWS +@@ -8,8 +8,6 @@ Backported from 8.0.28 + (CVE-2023-0567). (Tim Düsterhus) + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) +- +-- FPM: + . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart + request body). (CVE-2023-0662) (Jakub Zelenka) + +-- +2.39.1 + @@ -126,7 +126,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: %{?scl_prefix}php Version: %{upver}%{?rcver:~%{rcver}} -Release: 15%{?dist} +Release: 16%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend # TSRM is licensed under BSD @@ -206,6 +206,9 @@ Patch210: php-bug81727.patch Patch211: php-bug81726.patch Patch212: php-bug81738.patch Patch213: php-bug81740.patch +Patch214: php-bug81744.patch +Patch215: php-bug81746.patch +Patch216: php-cve-2023-0662.patch # Fixes for tests (300+) # Factory is droped from system tzdata @@ -979,6 +982,9 @@ sed -e 's/php-devel/%{?scl_prefix}php-devel/' -i scripts/phpize.in %patch211 -p1 -b .bug81726 %patch212 -p1 -b .bug81738 %patch213 -p1 -b .bug81740 +%patch214 -p1 -b .bug81744 +%patch215 -p1 -b .bug81746 +%patch216 -p1 -b .cve0662 # Fixes for tests %patch300 -p1 -b .datetests @@ -1949,6 +1955,14 @@ EOF %changelog +* Tue Feb 14 2023 Remi Collet <remi@remirepo.net> - 7.2.34-16 +- fix #81744: Password_verify() always return true with some hash + CVE-2023-0567 +- fix #81746: 1-byte array overrun in common path resolve code + CVE-2023-0568 +- fix DOS vulnerability when parsing multipart request body + CVE-2023-0662 + * Mon Dec 19 2022 Remi Collet <remi@remirepo.net> - 7.2.34-15 - pdo: fix #81740: PDO::quote() may return unquoted string CVE-2022-31631 |