diff options
-rw-r--r-- | failed.txt | 7 | ||||
-rw-r--r-- | php-cve-2024-5458.patch | 264 | ||||
-rw-r--r-- | php-cve-2024-8925.patch | 245 | ||||
-rw-r--r-- | php-cve-2024-8926.patch | 230 | ||||
-rw-r--r-- | php-cve-2024-8927.patch | 104 | ||||
-rw-r--r-- | php.spec | 45 |
6 files changed, 884 insertions, 11 deletions
@@ -1,12 +1,11 @@ -===== 5.6.40-40 (2024-04-11) +===== 5.6.40-43 (2024-09-27) $ grep -r 'Tests failed' /var/lib/mock/scl56*/build.log -/var/lib/mock/scl56el7x/build.log:Tests failed : 22 -/var/lib/mock/scl56el8x/build.log:Tests failed : 34 +/var/lib/mock/scl56el8x/build.log:Tests failed : 35 -el7x, el8x: +el8x: 2 related to tzdata, expired test cert and openssl policy diff --git a/php-cve-2024-5458.patch b/php-cve-2024-5458.patch new file mode 100644 index 0000000..8f8e23c --- /dev/null +++ b/php-cve-2024-5458.patch @@ -0,0 +1,264 @@ +From acadcd6a81bf11aacdc123fd241a5653c0f3605d Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Wed, 22 May 2024 22:25:02 +0200 +Subject: [PATCH 1/2] Fix GHSA-w8qr-v226-r27w + +We should not early-out with success status if we found an ipv6 +hostname, we should keep checking the rest of the conditions. +Because integrating the if-check of the ipv6 hostname in the +"Validate domain" if-check made the code hard to read, I extracted the +condition out to a separate function. This also required to make +a few pointers const in order to have some clean code. + +(cherry picked from commit 4066610b47e22c24cbee91be434a94357056a479) +(cherry picked from commit 08be64e40197fc12dca5f802d16748d9c3cb4cb4) +(cherry picked from commit 76362f9526afbd5565003d981f9507aaf62337f2) +(cherry picked from commit 87a7b8dab75e221a1fcd74cf34dc650f7253c12c) +(cherry picked from commit b919ad0323dbc3e1e1ac0f6ba8ec2ad380579918) +(cherry picked from commit f232d87846394315071ae115fcb8f1c4d1771eb3) +(cherry picked from commit 237878338b1cee3119e3f6d62c640b8cdb6d1169) +--- + ext/filter/logical_filters.c | 93 +++++++++++++++++++---- + ext/filter/tests/ghsa-w8qr-v226-r27w.phpt | 41 ++++++++++ + 2 files changed, 119 insertions(+), 15 deletions(-) + create mode 100644 ext/filter/tests/ghsa-w8qr-v226-r27w.phpt + +diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c +index 92a37f88ee..39260f3622 100644 +--- a/ext/filter/logical_filters.c ++++ b/ext/filter/logical_filters.c +@@ -66,6 +66,8 @@ + #define FORMAT_IPV4 4 + #define FORMAT_IPV6 6 + ++static int _php_filter_validate_ipv6(const char *str, int str_len TSRMLS_DC); ++ + static int php_filter_parse_int(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */ + long ctx_value; + int sign = 0, digit = 0; +@@ -445,6 +447,58 @@ void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + } + /* }}} */ + ++static int _php_filter_validate_domain(char * domain, int len) /* {{{ */ ++{ ++ char *e, *s, *t; ++ size_t l; ++ int hostname = 1; ++ unsigned char i = 1; ++ ++ s = domain; ++ l = len; ++ e = domain + l; ++ t = e - 1; ++ ++ /* Ignore trailing dot */ ++ if (*t == '.') { ++ e = t; ++ l--; ++ } ++ ++ /* The total length cannot exceed 253 characters (final dot not included) */ ++ if (l > 253) { ++ return 0; ++ } ++ ++ /* First char must be alphanumeric */ ++ if(*s == '.' || (hostname && !isalnum((int)*(unsigned char *)s))) { ++ return 0; ++ } ++ ++ while (s < e) { ++ if (*s == '.') { ++ /* The first and the last character of a label must be alphanumeric */ ++ if (*(s + 1) == '.' || (hostname && (!isalnum((int)*(unsigned char *)(s - 1)) || !isalnum((int)*(unsigned char *)(s + 1))))) { ++ return 0; ++ } ++ ++ /* Reset label length counter */ ++ i = 1; ++ } else { ++ if (i > 63 || (hostname && *s != '-' && !isalnum((int)*(unsigned char *)s))) { ++ return 0; ++ } ++ ++ i++; ++ } ++ ++ s++; ++ } ++ ++ return 1; ++} ++/* }}} */ ++ + static int is_userinfo_valid(char *str) + { + const char *valid = "-._~!$&'()*+,;=:"; +@@ -463,6 +517,14 @@ static int is_userinfo_valid(char *str) + return 1; + } + ++static zend_bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l TSRMLS_DC) ++{ ++ const char *e = s + l; ++ const char *t = e - 1; ++ ++ return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2 TSRMLS_CC); ++} ++ + void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + { + php_url *url; +@@ -482,25 +544,26 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + } + + if (url->scheme != NULL && (!strcasecmp(url->scheme, "http") || !strcasecmp(url->scheme, "https"))) { +- char *e, *s; ++ const char *s; ++ size_t l; + + if (url->host == NULL) { + goto bad_url; + } + +- e = url->host + strlen(url->host); + s = url->host; ++ l = strlen(s); + +- /* First char of hostname must be alphanumeric */ +- if(!isalnum((int)*(unsigned char *)s)) { +- goto bad_url; +- } ++ if ( ++ /* An IPv6 enclosed by square brackets is a valid hostname.*/ ++ !php_filter_is_valid_ipv6_hostname(s, l TSRMLS_CC) && ++ /* Validate domain. ++ * This includes a loose check for an IPv4 address. */ ++ !_php_filter_validate_domain(url->host, l) + +- while (s < e) { +- if (!isalnum((int)*(unsigned char *)s) && *s != '-' && *s != '.') { +- goto bad_url; +- } +- s++; ++ ) { ++ php_url_free(url); ++ RETURN_VALIDATION_FAILED + } + } + +@@ -581,7 +644,7 @@ void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + } + /* }}} */ + +-static int _php_filter_validate_ipv4(char *str, int str_len, int *ip) /* {{{ */ ++static int _php_filter_validate_ipv4(const char *str, int str_len, int *ip) /* {{{ */ + { + const char *end = str + str_len; + int num, m; +@@ -616,15 +679,15 @@ static int _php_filter_validate_ipv4(char *str, int str_len, int *ip) /* {{{ */ + } + /* }}} */ + +-static int _php_filter_validate_ipv6(char *str, int str_len TSRMLS_DC) /* {{{ */ ++static int _php_filter_validate_ipv6(const char *str, int str_len TSRMLS_DC) /* {{{ */ + { + int compressed = 0; + int blocks = 0; + int n; + char *ipv4; +- char *end; ++ const char *end; + int ip4elm[4]; +- char *s = str; ++ const char *s = str; + + if (!memchr(str, ':', str_len)) { + return 0; +diff --git a/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt b/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt +new file mode 100644 +index 0000000000..97867d4b07 +--- /dev/null ++++ b/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt +@@ -0,0 +1,41 @@ ++--TEST-- ++GHSA-w8qr-v226-r27w ++--EXTENSIONS-- ++filter ++--FILE-- ++<?php ++ ++function test($input) { ++ var_dump(filter_var($input, FILTER_VALIDATE_URL)); ++} ++ ++echo "--- These ones should fail ---\n"; ++test("http://t[est@127.0.0.1"); ++test("http://t[est@[::1]"); ++test("http://t[est@[::1"); ++test("http://t[est@::1]"); ++test("http://php.net\\@aliyun.com/aaa.do"); ++test("http://test[@2001:db8:3333:4444:5555:6666:1.2.3.4]"); ++test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4]"); ++test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4"); ++ ++echo "--- These ones should work ---\n"; ++test("http://test@127.0.0.1"); ++test("http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]"); ++test("http://test@[::1]"); ++ ++?> ++--EXPECT-- ++--- These ones should fail --- ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++--- These ones should work --- ++string(21) "http://test@127.0.0.1" ++string(50) "http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]" ++string(17) "http://test@[::1]" +-- +2.45.1 + +From aa6e34b7cb4ea37d5f7cab27a560df8f0b763908 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 4 Jun 2024 16:48:08 +0200 +Subject: [PATCH 2/2] NEWS + +(cherry picked from commit a1ff81b786bd519597e770795be114f5171f0648) +(cherry picked from commit ec1d5e6468479e64acc7fb8cb955f053b64ea9a0) +(cherry picked from commit cfe1b1acead13b6af163f3ce947d3a1dbded82a0) +(cherry picked from commit 6b6444a1b72d6249cfa592f20395efe67ca55f73) +(cherry picked from commit 8d4db37794eff4761a336d7cee53d47f0eb0d313) +(cherry picked from commit 573b921a612068f66f6540b69b0a9bc9f372ecf1) +(cherry picked from commit 20ceeb85afad56df396a61247f2cb4cb9efb9a6b) +--- + NEWS | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/NEWS b/NEWS +index 163bc6bdba..c10febbfa1 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.1.29 ++ ++- Filter: ++ . Fixed bug GHSA-w8qr-v226-r27w (Filter bypass in filter_var FILTER_VALIDATE_URL). ++ (CVE-2024-5458) (nielsdos) ++ + Backported from 8.1.28 + + - Standard: +-- +2.45.1 + diff --git a/php-cve-2024-8925.patch b/php-cve-2024-8925.patch new file mode 100644 index 0000000..739a5a5 --- /dev/null +++ b/php-cve-2024-8925.patch @@ -0,0 +1,245 @@ +From 1dc4f3e134d4b5fe0776d46f1342c603fdff072f Mon Sep 17 00:00:00 2001 +From: Arnaud Le Blanc <arnaud.lb@gmail.com> +Date: Mon, 9 Sep 2024 15:22:07 +0200 +Subject: [PATCH 4/9] Fix GHSA-9pqp-7h25-4f32 + +multipart/form-data boundaries larger than the read buffer result in erroneous +parsing, which violates data integrity. + +Limit boundary size, as allowed by RFC 1521: + + Encapsulation boundaries [...] must be no longer than 70 characters, not + counting the two leading hyphens. + +We correctly parse payloads with boundaries of length up to +FILLUNIT-strlen("\r\n--") bytes, so allow this for BC. + +(cherry picked from commit 19b49258d0c5a61398d395d8afde1123e8d161e0) +(cherry picked from commit 2b0daf421c162376892832588eccdfa9a286ed09) +(cherry picked from commit a24ac172f52e75101913f3946cfa5515f723c99f) +(cherry picked from commit 08f0adf0700f8bbaa4fd75b7a694bbd9ae45300d) +(cherry picked from commit 5731a40507feea683591addf3599d210cd7a1fd9) +(cherry picked from commit c9e67e9debe6ed0b313ebc6769a3ca0e417cd781) +(cherry picked from commit cc487bc778a079891c67e927edf0fc1a46f0e5e3) +--- + main/rfc1867.c | 7 ++ + tests/basic/GHSA-9pqp-7h25-4f32.inc | 3 + + tests/basic/GHSA-9pqp-7h25-4f32.phpt | 100 +++++++++++++++++++++++++++ + 3 files changed, 110 insertions(+) + create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.inc + create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.phpt + +diff --git a/main/rfc1867.c b/main/rfc1867.c +index 407cc3be14..1efd28298e 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -763,6 +763,13 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + boundary_len = boundary_end-boundary; + } + ++ /* Boundaries larger than FILLUNIT-strlen("\r\n--") characters lead to ++ * erroneous parsing */ ++ if (boundary_len > FILLUNIT-strlen("\r\n--")) { ++ sapi_module.sapi_error(E_WARNING, "Boundary too large in multipart/form-data POST data"); ++ return; ++ } ++ + /* Initialize the buffer */ + if (!(mbuff = multipart_buffer_new(boundary, boundary_len TSRMLS_CC))) { + sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer"); +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.inc b/tests/basic/GHSA-9pqp-7h25-4f32.inc +new file mode 100644 +index 0000000000..adf72a361a +--- /dev/null ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.inc +@@ -0,0 +1,3 @@ ++<?php ++print "Hello world\n"; ++var_dump($_POST); +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +new file mode 100644 +index 0000000000..af81916370 +--- /dev/null ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +@@ -0,0 +1,100 @@ ++--TEST-- ++GHSA-9pqp-7h25-4f32 ++--SKIPIF-- ++<?php ++if (!getenv('TEST_PHP_CGI_EXECUTABLE')) { ++ die("skip php-cgi not available"); ++} ++?> ++--FILE-- ++<?php ++ ++const FILLUNIT = 5 * 1024; ++ ++function test($boundaryLen) { ++ printf("Boundary len: %d\n", $boundaryLen); ++ ++ $cmd = [ ++ getenv('TEST_PHP_CGI_EXECUTABLE'), ++ '-C', ++ '-n', ++ __DIR__ . '/GHSA-9pqp-7h25-4f32.inc', ++ ]; ++ ++ $boundary = str_repeat('A', $boundaryLen); ++ $body = "" ++ . "--$boundary\r\n" ++ . "Content-Disposition: form-data; name=\"koko\"\r\n" ++ . "\r\n" ++ . "BBB\r\n--" . substr($boundary, 0, -1) . "CCC\r\n" ++ . "--$boundary--\r\n" ++ ; ++ ++ $env = array_merge($_ENV, [ ++ 'REDIRECT_STATUS' => '1', ++ 'CONTENT_TYPE' => "multipart/form-data; boundary=$boundary", ++ 'CONTENT_LENGTH' => strlen($body), ++ 'REQUEST_METHOD' => 'POST', ++ 'SCRIPT_FILENAME' => __DIR__ . '/GHSA-9pqp-7h25-4f32.inc', ++ ]); ++ ++ $spec = [ ++ 0 => ['pipe', 'r'], ++ 1 => STDOUT, ++ 2 => STDOUT, ++ ]; ++ ++ $pipes = []; ++ ++ print "Starting...\n"; ++ ++ $handle = proc_open($cmd, $spec, $pipes, getcwd(), $env); ++ ++ fwrite($pipes[0], $body); ++ ++ $status = proc_close($handle); ++ ++ print "\n"; ++} ++ ++for ($offset = -1; $offset <= 1; $offset++) { ++ test(FILLUNIT - strlen("\r\n--") + $offset); ++} ++ ++?> ++--EXPECTF-- ++Boundary len: 5115 ++Starting... ++X-Powered-By: %s ++Content-type: text/html; charset=UTF-8 ++ ++Hello world ++array(1) { ++ ["koko"]=> ++ string(5124) "BBB ++--AAA%sCCC" ++} ++ ++Boundary len: 5116 ++Starting... ++X-Powered-By: %s ++Content-type: text/html; charset=UTF-8 ++ ++Hello world ++array(1) { ++ ["koko"]=> ++ string(5125) "BBB ++--AAA%sCCC" ++} ++ ++Boundary len: 5117 ++Starting... ++X-Powered-By: %s ++Content-type: text/html; charset=UTF-8 ++ ++<br /> ++<b>Warning</b>: Boundary too large in multipart/form-data POST data in <b>Unknown</b> on line <b>0</b><br /> ++Hello world ++array(0) { ++} ++ +-- +2.46.1 + +From 8747962af4a9a76d81b55b4455896da40cd523c6 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Mon, 23 Sep 2024 18:54:31 +0100 +Subject: [PATCH 7/9] Skip GHSA-9pqp-7h25-4f32 test on Windows + +(cherry picked from commit c70e25630832fa10d421328eed2b8e1a36af7a64) +(cherry picked from commit c75683864f6e4188439e8ca2adbb05824918be12) +(cherry picked from commit 2fd1b83817d20523e72bef3ad524cd5797f51acf) +(cherry picked from commit 79eace3a64544088738d2fd341407cc32fe3ecaf) +(cherry picked from commit 0c9258e4914695ca21b3d0cd3b1746bfc926f02e) +(cherry picked from commit 2d5ff57eb7a36f9f0655c7073c4c702a903d9005) +(cherry picked from commit d5931f3c995e5d1d92289f0acbbaef1678d911a6) +--- + tests/basic/GHSA-9pqp-7h25-4f32.phpt | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +index af81916370..29bcb6557d 100644 +--- a/tests/basic/GHSA-9pqp-7h25-4f32.phpt ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +@@ -5,6 +5,9 @@ GHSA-9pqp-7h25-4f32 + if (!getenv('TEST_PHP_CGI_EXECUTABLE')) { + die("skip php-cgi not available"); + } ++if (substr(PHP_OS, 0, 3) == 'WIN') { ++ die("skip not for Windows in CI - probably resource issue"); ++} + ?> + --FILE-- + <?php +-- +2.46.1 + +From 355cd5cb0c3813ae49d88693cff410281413c2f6 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 26 Sep 2024 15:49:03 +0200 +Subject: [PATCH 9/9] adapt GHSA-9pqp-7h25-4f32 test for 7.x + +(cherry picked from commit 29065f33f37f99ba33254cb23c941647bcd7372c) +(cherry picked from commit 87ed9429a17e38daec4dcfd7a3c3db194197ccb3) +(cherry picked from commit d97de82afe8696b6d76cc11bc7b6d6c2652d06d9) +(cherry picked from commit 64a9dfdec2cb530428c9cbe90f98f346c5d23797) +(cherry picked from commit fb9688a470070f0ab656e2f94efbee2988a30eaf) +--- + tests/basic/GHSA-9pqp-7h25-4f32.phpt | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +index 29bcb6557d..b913edc1c4 100644 +--- a/tests/basic/GHSA-9pqp-7h25-4f32.phpt ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +@@ -21,8 +21,10 @@ function test($boundaryLen) { + getenv('TEST_PHP_CGI_EXECUTABLE'), + '-C', + '-n', ++ '-dlog_errors=1', + __DIR__ . '/GHSA-9pqp-7h25-4f32.inc', + ]; ++ $cmd = implode(' ', $cmd); + + $boundary = str_repeat('A', $boundaryLen); + $body = "" +@@ -92,11 +94,10 @@ array(1) { + + Boundary len: 5117 + Starting... ++PHP Warning: Boundary too large in multipart/form-data POST data in Unknown on line 0 + X-Powered-By: %s + Content-type: text/html; charset=UTF-8 + +-<br /> +-<b>Warning</b>: Boundary too large in multipart/form-data POST data in <b>Unknown</b> on line <b>0</b><br /> + Hello world + array(0) { + } +-- +2.46.1 + diff --git a/php-cve-2024-8926.patch b/php-cve-2024-8926.patch new file mode 100644 index 0000000..679ad7b --- /dev/null +++ b/php-cve-2024-8926.patch @@ -0,0 +1,230 @@ +From 0bd3bd616f6139dd1e076bb2e0df1a74ef298c76 Mon Sep 17 00:00:00 2001 +From: Jan Ehrhardt <github@ehrhardt.nl> +Date: Wed, 5 Jun 2024 20:42:45 +0200 +Subject: [PATCH 1/9] Fix GHSA-3qgc-jrrr-25jv + +--- + sapi/cgi/cgi_main.c | 23 ++++++++++++++- + sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt | 38 +++++++++++++++++++++++++ + 2 files changed, 60 insertions(+), 1 deletion(-) + create mode 100644 sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt + +diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c +index a735056e9a..1996eb6e87 100644 +--- a/sapi/cgi/cgi_main.c ++++ b/sapi/cgi/cgi_main.c +@@ -1830,8 +1830,13 @@ int main(int argc, char *argv[]) + } + } + ++ /* Apache CGI will pass the query string to the command line if it doesn't contain a '='. ++ * This can create an issue where a malicious request can pass command line arguments to ++ * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode, ++ * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`. ++ * Therefore, this code only prevents passing arguments if the query string starts with a '-'. ++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */ + if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) { +- /* we've got query string that has no = - apache CGI will pass it to command line */ + unsigned char *p; + decoded_query_string = strdup(query_string); + php_url_decode(decoded_query_string, strlen(decoded_query_string)); +@@ -1841,6 +1846,22 @@ int main(int argc, char *argv[]) + if(*p == '-') { + skip_getopt = 1; + } ++ ++ /* On Windows we have to take into account the "best fit" mapping behaviour. */ ++#ifdef PHP_WIN32 ++ if (*p >= 0x80) { ++ wchar_t wide_buf[1]; ++ wide_buf[0] = *p; ++ char char_buf[4]; ++ size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]); ++ size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]); ++ if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0 ++ || char_buf[0] == '-') { ++ skip_getopt = 1; ++ } ++ } ++#endif ++ + free(decoded_query_string); + } + +diff --git a/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt +new file mode 100644 +index 0000000000..fd2fcdfbf8 +--- /dev/null ++++ b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt +@@ -0,0 +1,38 @@ ++--TEST-- ++GHSA-3qgc-jrrr-25jv ++--SKIPIF-- ++<?php ++include 'skipif.inc'; ++if (PHP_OS_FAMILY !== "Windows") die("skip Only for Windows"); ++ ++$codepage = trim(shell_exec("powershell Get-ItemPropertyValue HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage ACP")); ++if ($codepage !== '932' && $codepage !== '936' && $codepage !== '950') die("skip Wrong codepage"); ++?> ++--FILE-- ++<?php ++include 'include.inc'; ++ ++$filename = __DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php"; ++$script = '<?php echo "hello "; echo "world"; ?>'; ++file_put_contents($filename, $script); ++ ++$php = get_cgi_path(); ++reset_env_vars(); ++ ++putenv("SERVER_NAME=Test"); ++putenv("SCRIPT_FILENAME=$filename"); ++putenv("QUERY_STRING=%ads"); ++putenv("REDIRECT_STATUS=1"); ++ ++passthru("$php -s"); ++ ++?> ++--CLEAN-- ++<?php ++@unlink(__DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php"); ++?> ++--EXPECTF-- ++X-Powered-By: PHP/%s ++Content-type: %s ++ ++hello world +-- +2.46.1 + +From c5daf2e9cc0bc6b6587b67de97b9cb188898da8e Mon Sep 17 00:00:00 2001 +From: Jan Ehrhardt <github@ehrhardt.nl> +Date: Thu, 6 Jun 2024 23:48:14 +0200 +Subject: [PATCH 2/9] Fix GHSA-3qgc-jrrr-25jv - VC11 + +--- + sapi/cgi/cgi_main.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c +index 1996eb6e87..3051a89bce 100644 +--- a/sapi/cgi/cgi_main.c ++++ b/sapi/cgi/cgi_main.c +@@ -1851,10 +1851,12 @@ int main(int argc, char *argv[]) + #ifdef PHP_WIN32 + if (*p >= 0x80) { + wchar_t wide_buf[1]; +- wide_buf[0] = *p; + char char_buf[4]; +- size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]); +- size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]); ++ size_t wide_buf_len; ++ size_t char_buf_len; ++ wide_buf[0] = *p; ++ wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]); ++ char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]); + if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0 + || char_buf[0] == '-') { + skip_getopt = 1; +-- +2.46.1 + +From ed5aebf7d65fb67b399f9320f704b5e2bb165117 Mon Sep 17 00:00:00 2001 +From: Jan Ehrhardt <github@ehrhardt.nl> +Date: Sun, 9 Jun 2024 20:15:52 +0200 +Subject: [PATCH 3/9] NEWS: Add backport from 8.1.29 + +--- + NEWS | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/NEWS b/NEWS +index c10febbfa1..b4be05a2d2 100644 +--- a/NEWS ++++ b/NEWS +@@ -3,6 +3,10 @@ PHP NEWS + + Backported from 8.1.29 + ++- CGI: ++ . Fixed bug GHSA-3qgc-jrrr-25jv (Bypass of CVE-2012-1823, Argument Injection ++ in PHP-CGI). (CVE-2024-4577) (nielsdos) ++ + - Filter: + . Fixed bug GHSA-w8qr-v226-r27w (Filter bypass in filter_var FILTER_VALIDATE_URL). + (CVE-2024-5458) (nielsdos) +-- +2.46.1 + +From d371734993ed88e9ef42c47430ae8097c5ee03f0 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Fri, 14 Jun 2024 19:49:22 +0200 +Subject: [PATCH 5/9] Fix GHSA-p99j-rfp4-xqvq + +It's no use trying to work around whatever the operating system and Apache +do because we'll be fighting that until eternity. +Change the skip_getopt condition such that when we're running in +CGI or FastCGI mode we always skip the argument parsing. +This is a BC break, but this seems to be the only way to get rid of this +class of issues. + +(cherry picked from commit abcfd980bfa03298792fd3aba051c78d52f10642) +(cherry picked from commit 2d2552e092b6ff32cd823692d512f126ee629842) +(cherry picked from commit 1158d06f0b20532ab7309cb20f0be843f9662e3c) +(cherry picked from commit 89c66773413267949de995671bfb4bd03c34fbf9) +(cherry picked from commit 53a0269aa1d952eec1c65e0e0d3e9800e0427ded) +(cherry picked from commit 56f24340b2cd718d54fca9bc95cbf1f34b50b71f) +(cherry picked from commit 493b4986d3cb8bfaccbab82628a4b91044670572) +--- + sapi/cgi/cgi_main.c | 25 +++++++------------------ + 1 file changed, 7 insertions(+), 18 deletions(-) + +diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c +index 3051a89bce..60b8e981cc 100644 +--- a/sapi/cgi/cgi_main.c ++++ b/sapi/cgi/cgi_main.c +@@ -1835,8 +1835,13 @@ int main(int argc, char *argv[]) + * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode, + * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`. + * Therefore, this code only prevents passing arguments if the query string starts with a '-'. +- * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */ ++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue. ++ * However, Windows has lots of conversion rules and command line parsing rules that ++ * are too difficult and dangerous to reliably emulate. */ + if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) { ++#ifdef PHP_WIN32 ++ skip_getopt = cgi || fastcgi; ++#else + unsigned char *p; + decoded_query_string = strdup(query_string); + php_url_decode(decoded_query_string, strlen(decoded_query_string)); +@@ -1847,24 +1852,8 @@ int main(int argc, char *argv[]) + skip_getopt = 1; + } + +- /* On Windows we have to take into account the "best fit" mapping behaviour. */ +-#ifdef PHP_WIN32 +- if (*p >= 0x80) { +- wchar_t wide_buf[1]; +- char char_buf[4]; +- size_t wide_buf_len; +- size_t char_buf_len; +- wide_buf[0] = *p; +- wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]); +- char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]); +- if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0 +- || char_buf[0] == '-') { +- skip_getopt = 1; +- } +- } +-#endif +- + free(decoded_query_string); ++#endif + } + + while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { +-- +2.46.1 + diff --git a/php-cve-2024-8927.patch b/php-cve-2024-8927.patch new file mode 100644 index 0000000..16b1f44 --- /dev/null +++ b/php-cve-2024-8927.patch @@ -0,0 +1,104 @@ +From 7c4412aa8d7727eb8a36db7d98c0f7b6e86cc5ea Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Tue, 18 Jun 2024 21:28:26 +0200 +Subject: [PATCH 6/9] Fix GHSA-94p6-54jq-9mwp + +Apache only generates REDIRECT_STATUS, so explicitly check for that +if the server name is Apache, don't allow other variable names. +Furthermore, redirect.so and Netscape no longer exist, so +remove those entries as we can't check their server name anymore. + +We now also check for the configuration override *first* such that it +always take precedence. This would allow for a mitigation path if +something like this happens in the future. + +(cherry picked from commit 48808d98f4fc2a05193cdcc1aedd6c66816450f1) +(cherry picked from commit 8aa748ee0657cdee8d883ba50d04b68bc450f686) +(cherry picked from commit c7308ba7cd0533501b40eba255602bb5e085550f) +(cherry picked from commit 21e2b0ab382a898f627c97d39f5e5afc2431afe7) +(cherry picked from commit 74f1553070cb6237e25945407be7f75a43736113) +(cherry picked from commit 1e522a66b2b5376545c3e3dfc743e4e6614aade9) +(cherry picked from commit 234a673bb5bee58ce752d6fefa4cba99435ae21c) +--- + sapi/cgi/cgi_main.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c +index 60b8e981cc..ccb873aed8 100644 +--- a/sapi/cgi/cgi_main.c ++++ b/sapi/cgi/cgi_main.c +@@ -1942,18 +1942,17 @@ int main(int argc, char *argv[]) + + /* check force_cgi after startup, so we have proper output */ + if (cgi && CGIG(force_redirect)) { +- /* Apache will generate REDIRECT_STATUS, +- * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS. +- * redirect.so and installation instructions available from +- * http://www.koehntopp.de/php. +- * -- kk@netuse.de +- */ +- if (!getenv("REDIRECT_STATUS") && +- !getenv ("HTTP_REDIRECT_STATUS") && +- /* this is to allow a different env var to be configured +- * in case some server does something different than above */ +- (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env))) +- ) { ++ /* This is to allow a different environment variable to be configured ++ * in case the we cannot auto-detect which environment variable to use. ++ * Checking this first to allow user overrides in case the environment ++ * variable can be set by an untrusted party. */ ++ const char *redirect_status_env = CGIG(redirect_status_env); ++ if (!redirect_status_env) { ++ /* Apache will generate REDIRECT_STATUS. */ ++ redirect_status_env = "REDIRECT_STATUS"; ++ } ++ ++ if (!getenv(redirect_status_env)) { + zend_try { + SG(sapi_headers).http_response_code = 400; + PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\ +-- +2.46.1 + +From fb90cb1cb6e478b333750c18cacd46e3e7984dcd Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 26 Sep 2024 11:50:54 +0200 +Subject: [PATCH 8/9] NEWS for 8.1.30 backports + +(cherry picked from commit af3fb385e7b328ab89db26ec712d89c7096f0743) +(cherry picked from commit 1154fbd3ddfa418bf2492c5366adaefb47c47737) +(cherry picked from commit b4667e4ebe241d95775962b1e8b24788e7945de2) +(cherry picked from commit e80cb90b00aa403a5aa995f612ecb358323e9572) +(cherry picked from commit fbd3eff22ba8becf30263ddf6ab92a9c2ca93181) +(cherry picked from commit 9a3477d3c48272520840f9e20a7135e929e68c0e) +--- + NEWS | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/NEWS b/NEWS +index b4be05a2d2..957508cd64 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,19 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.1.30 ++ ++- CGI: ++ . Fixed bug GHSA-p99j-rfp4-xqvq (Bypass of CVE-2024-4577, Parameter Injection ++ Vulnerability). (CVE-2024-8926) (nielsdos) ++ . Fixed bug GHSA-94p6-54jq-9mwp (cgi.force_redirect configuration is ++ bypassable due to the environment variable collision). (CVE-2024-8927) ++ (nielsdos) ++ ++- SAPI: ++ . Fixed bug GHSA-9pqp-7h25-4f32 (Erroneous parsing of multipart form data). ++ (CVE-2024-8925) (Arnaud) ++ + Backported from 8.1.29 + + - CGI: +-- +2.46.1 + @@ -60,13 +60,15 @@ %global mysql_sock %(mysql_config --socket 2>/dev/null || echo /var/lib/mysql/mysql.sock) %ifarch aarch64 -%global oraclever 19.19 +%global oraclever 19.24 +%global oraclemax 20 %global oraclelib 19.1 -%global oracledir 19.19 +%global oracledir 19.24 %else -%global oraclever 21.13 -%global oraclelib 21.1 -%global oracledir 21 +%global oraclever 23.5 +%global oraclemax 24 +%global oraclelib 23.1 +%global oracledir 23 %endif # Build for LiteSpeed Web Server (LSAPI) @@ -139,7 +141,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: %{?scl_prefix}php Version: 5.6.40 -Release: 40%{?dist} +Release: 43%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend # TSRM is licensed under BSD @@ -261,6 +263,10 @@ Patch264: php-cve-2023-3823.patch Patch265: php-cve-2023-3824.patch Patch266: php-cve-2024-2756.patch Patch267: php-cve-2024-3096.patch +Patch268: php-cve-2024-5458.patch +Patch269: php-cve-2024-8925.patch +Patch270: php-cve-2024-8926.patch +Patch271: php-cve-2024-8927.patch # Fixes for tests (300+) # Factory is droped from system tzdata @@ -702,7 +708,7 @@ BuildRequires: oracle-instantclient%{oraclever}-devel Requires: libclntsh.so.%{oraclelib} AutoReq: 0 %else -BuildRequires: oracle-instantclient-devel >= %{oraclever} +BuildRequires: (oracle-instantclient-devel >= %{oraclever} with oracle-instantclient-devel < %{oraclemax}) %endif Requires: %{?scl_prefix}php-pdo%{?_isa} = %{version}-%{release} Provides: %{?scl_prefix}php_database @@ -930,7 +936,11 @@ Group: System Environment/Libraries License: PHP Requires: %{?scl_prefix}php-common%{?_isa} = %{version}-%{release} # Upstream requires 4.0, we require 69.1 to ensure use of libicu69 +%if 0%{?rhel} BuildRequires: libicu-devel = 69.1 +%else +BuildRequires: libicu-devel +%endif %description intl The %{?scl_prefix}php-intl package contains a dynamic shared object that will add @@ -1055,6 +1065,10 @@ sed -e 's/php-devel/%{?scl_prefix}php-devel/' -i scripts/phpize.in %patch -P265 -p1 -b .cve3824 %patch -P266 -p1 -b .cve2756 %patch -P267 -p1 -b .cve3096 +%patch -P268 -p1 -b .cve5458 +%patch -P269 -p1 -b .cve8925 +%patch -P270 -p1 -b .cve8926 +%patch -P271 -p1 -b .cve8927 # Fixes for tests %patch -P300 -p1 -b .datetests @@ -2005,6 +2019,23 @@ EOF %changelog +* Thu Sep 26 2024 Remi Collet <remi@remirepo.net> - 5.6.40-43 +- Fix Bypass of CVE-2012-1823, Argument Injection in PHP-CGI + CVE-2024-4577 +- Fix Bypass of CVE-2024-4577, Parameter Injection Vulnerability + CVE-2024-8926 +- Fix cgi.force_redirect configuration is bypassable due to the environment variable collision + CVE-2024-8927 +- Fix Erroneous parsing of multipart form data + CVE-2024-8925 + +* Wed Jul 31 2024 Remi Collet <remi@remirepo.net> - 5.6.40-42 +- use oracle client library version 23.5 on x86_64 + +* Tue Jun 4 2024 Remi Collet <remi@remirepo.net> - 5.6.40-41 +- Fix filter bypass in filter_var FILTER_VALIDATE_URL + CVE-2024-5458 + * Wed Apr 10 2024 Remi Collet <remi@remirepo.net> - 5.6.40-40 - use oracle client library version 21.13 - Fix __Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix |