Fix Null byte termination in dns_get_record() GHSA-www2-q4fc-65wf
Fix Heap buffer overflow in array_merge() CVE-2025-14178 Fix Information Leak of Memory in getimagesize CVE-2025-14177 Resolves: RHEL-141193
This commit is contained in:
parent
24221dbf44
commit
79b91547ee
103
php-cve-2025-14177.patch
Normal file
103
php-cve-2025-14177.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From ed665eb1903737d2b52b27368b155f6208604ed9 Mon Sep 17 00:00:00 2001
|
||||
From: Niels Dossche <7771979+ndossche@users.noreply.github.com>
|
||||
Date: Tue, 25 Nov 2025 23:11:38 +0100
|
||||
Subject: [PATCH 1/5] Fix GH-20584: Information Leak of Memory
|
||||
|
||||
The string added had uninitialized memory due to
|
||||
php_read_stream_all_chunks() not moving the buffer position, resulting
|
||||
in the same data always being overwritten instead of new data being
|
||||
added to the end of the buffer.
|
||||
|
||||
This is backport as there is a security impact as described in
|
||||
GHSA-3237-qqm7-mfv7 .
|
||||
|
||||
(cherry picked from commit c5f28c7cf0a052f48e47877c7aa5c5bcc54f1cfc)
|
||||
---
|
||||
ext/standard/image.c | 17 +++++++++++-
|
||||
ext/standard/tests/image/gh20584.phpt | 39 +++++++++++++++++++++++++++
|
||||
2 files changed, 55 insertions(+), 1 deletion(-)
|
||||
create mode 100644 ext/standard/tests/image/gh20584.phpt
|
||||
|
||||
diff --git a/ext/standard/image.c b/ext/standard/image.c
|
||||
index 419522c6a2e..69f18d100f5 100644
|
||||
--- a/ext/standard/image.c
|
||||
+++ b/ext/standard/image.c
|
||||
@@ -424,6 +424,21 @@ static int php_skip_variable(php_stream * stream)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
+static size_t php_read_stream_all_chunks(php_stream *stream, char *buffer, size_t length)
|
||||
+{
|
||||
+ size_t read_total = 0;
|
||||
+ do {
|
||||
+ ssize_t read_now = php_stream_read(stream, buffer, length - read_total);
|
||||
+ read_total += read_now;
|
||||
+ if (read_now < stream->chunk_size && read_total != length) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ buffer += read_now;
|
||||
+ } while (read_total < length);
|
||||
+
|
||||
+ return read_total;
|
||||
+}
|
||||
+
|
||||
/* {{{ php_read_APP */
|
||||
static int php_read_APP(php_stream * stream, unsigned int marker, zval *info)
|
||||
{
|
||||
@@ -440,7 +455,7 @@ static int php_read_APP(php_stream * stream, unsigned int marker, zval *info)
|
||||
|
||||
buffer = emalloc(length);
|
||||
|
||||
- if (php_stream_read(stream, buffer, (size_t) length) != length) {
|
||||
+ if (php_read_stream_all_chunks(stream, buffer, length) != length) {
|
||||
efree(buffer);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/ext/standard/tests/image/gh20584.phpt b/ext/standard/tests/image/gh20584.phpt
|
||||
new file mode 100644
|
||||
index 00000000000..d117f218202
|
||||
--- /dev/null
|
||||
+++ b/ext/standard/tests/image/gh20584.phpt
|
||||
@@ -0,0 +1,39 @@
|
||||
+--TEST--
|
||||
+GH-20584 (Information Leak of Memory)
|
||||
+--CREDITS--
|
||||
+Nikita Sveshnikov (Positive Technologies)
|
||||
+--FILE--
|
||||
+<?php
|
||||
+// Minimal PoC: corruption/uninitialized memory leak when reading APP1 via php://filter
|
||||
+$file = __DIR__ . '/gh20584.jpg';
|
||||
+
|
||||
+// Make APP1 large enough so it is read in multiple chunks
|
||||
+$chunk = 8192;
|
||||
+$tail = 123;
|
||||
+$payload = str_repeat('A', $chunk) . str_repeat('B', $chunk) . str_repeat('Z',
|
||||
+$tail);
|
||||
+$app1Len = 2 + strlen($payload);
|
||||
+
|
||||
+// Minimal JPEG: SOI + APP1 + SOF0(1x1) + EOI
|
||||
+$sof = "\xFF\xC0" . pack('n', 11) . "\x08" . pack('n',1) . pack('n',1) .
|
||||
+"\x01\x11\x00";
|
||||
+$jpeg = "\xFF\xD8" . "\xFF\xE1" . pack('n', $app1Len) . $payload . $sof .
|
||||
+"\xFF\xD9";
|
||||
+file_put_contents($file, $jpeg);
|
||||
+
|
||||
+// Read through a filter to enforce multiple reads
|
||||
+$src = 'php://filter/read=string.rot13|string.rot13/resource=' . $file;
|
||||
+$info = null;
|
||||
+@getimagesize($src, $info);
|
||||
+$exp = $payload;
|
||||
+$ret = $info['APP1'];
|
||||
+
|
||||
+var_dump($ret === $exp);
|
||||
+
|
||||
+?>
|
||||
+--CLEAN--
|
||||
+<?php
|
||||
+@unlink(__DIR__ . '/gh20584.jpg');
|
||||
+?>
|
||||
+--EXPECT--
|
||||
+bool(true)
|
||||
--
|
||||
2.52.0
|
||||
|
||||
62
php-cve-2025-14178.patch
Normal file
62
php-cve-2025-14178.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From e4516e52979e8b67d9d35dfdbcc5dc7368263fa2 Mon Sep 17 00:00:00 2001
|
||||
From: Niels Dossche <7771979+ndossche@users.noreply.github.com>
|
||||
Date: Sun, 9 Nov 2025 13:23:11 +0100
|
||||
Subject: [PATCH 3/5] Fix GHSA-h96m-rvf9-jgm2
|
||||
|
||||
(cherry picked from commit 8b801151bd54b36aae4593ed6cfc096e8122b415)
|
||||
---
|
||||
ext/standard/array.c | 7 ++++++-
|
||||
.../tests/array/GHSA-h96m-rvf9-jgm2.phpt | 16 ++++++++++++++++
|
||||
2 files changed, 22 insertions(+), 1 deletion(-)
|
||||
create mode 100644 ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt
|
||||
|
||||
diff --git a/ext/standard/array.c b/ext/standard/array.c
|
||||
index 4b68040adc8..2960713d00e 100644
|
||||
--- a/ext/standard/array.c
|
||||
+++ b/ext/standard/array.c
|
||||
@@ -3798,7 +3798,7 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET
|
||||
int argc, i;
|
||||
zval *src_entry;
|
||||
HashTable *src, *dest;
|
||||
- uint32_t count = 0;
|
||||
+ uint64_t count = 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(0, -1)
|
||||
Z_PARAM_VARIADIC('+', args, argc)
|
||||
@@ -3818,6 +3818,11 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET
|
||||
count += zend_hash_num_elements(Z_ARRVAL_P(arg));
|
||||
}
|
||||
|
||||
+ if (UNEXPECTED(count >= HT_MAX_SIZE)) {
|
||||
+ zend_throw_error(NULL, "The total number of elements must be lower than %u", HT_MAX_SIZE);
|
||||
+ RETURN_THROWS();
|
||||
+ }
|
||||
+
|
||||
if (argc == 2) {
|
||||
zval *ret = NULL;
|
||||
|
||||
diff --git a/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt b/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt
|
||||
new file mode 100644
|
||||
index 00000000000..2e3e85357e1
|
||||
--- /dev/null
|
||||
+++ b/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt
|
||||
@@ -0,0 +1,16 @@
|
||||
+--TEST--
|
||||
+GHSA-h96m-rvf9-jgm2
|
||||
+--FILE--
|
||||
+<?php
|
||||
+
|
||||
+$power = 20; // Chosen to be well within a memory_limit
|
||||
+$arr = range(0, 2**$power);
|
||||
+try {
|
||||
+ array_merge(...array_fill(0, 2**(32-$power), $arr));
|
||||
+} catch (Error $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+
|
||||
+?>
|
||||
+--EXPECTF--
|
||||
+The total number of elements must be lower than %d
|
||||
--
|
||||
2.52.0
|
||||
|
||||
231
php-ghsa-www2-q4fc-65wf.patch
Normal file
231
php-ghsa-www2-q4fc-65wf.patch
Normal file
@ -0,0 +1,231 @@
|
||||
From 52c5762a902e8731b7068ded027fbd780f5a1991 Mon Sep 17 00:00:00 2001
|
||||
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
|
||||
Date: Sat, 6 Sep 2025 21:55:13 +0200
|
||||
Subject: [PATCH 4/5] Fix GHSA-www2-q4fc-65wf
|
||||
|
||||
(cherry picked from commit ed70b1ea43a9b7ffa2f53b3e5d6ba403f37ae81c)
|
||||
---
|
||||
ext/standard/basic_functions.c | 12 ++--
|
||||
ext/standard/dns.c | 6 +-
|
||||
ext/standard/dns_win32.c | 6 +-
|
||||
.../tests/network/ghsa-www2-q4fc-65wf.phpt | 62 +++++++++++++++++++
|
||||
4 files changed, 74 insertions(+), 12 deletions(-)
|
||||
create mode 100644 ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt
|
||||
|
||||
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
|
||||
index 876ef347ebf..9eba6d5a14c 100755
|
||||
--- a/ext/standard/basic_functions.c
|
||||
+++ b/ext/standard/basic_functions.c
|
||||
@@ -633,7 +633,7 @@ PHP_FUNCTION(inet_pton)
|
||||
char buffer[17];
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
- Z_PARAM_STRING(address, address_len)
|
||||
+ Z_PARAM_PATH(address, address_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
@@ -670,7 +670,7 @@ PHP_FUNCTION(ip2long)
|
||||
#endif
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
- Z_PARAM_STRING(addr, addr_len)
|
||||
+ Z_PARAM_PATH(addr, addr_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
#ifdef HAVE_INET_PTON
|
||||
@@ -2265,8 +2265,8 @@ PHP_FUNCTION(getservbyname)
|
||||
struct servent *serv;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 2)
|
||||
- Z_PARAM_STRING(name, name_len)
|
||||
- Z_PARAM_STRING(proto, proto_len)
|
||||
+ Z_PARAM_PATH(name, name_len)
|
||||
+ Z_PARAM_PATH(proto, proto_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
|
||||
@@ -2309,7 +2309,7 @@ PHP_FUNCTION(getservbyport)
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 2)
|
||||
Z_PARAM_LONG(port)
|
||||
- Z_PARAM_STRING(proto, proto_len)
|
||||
+ Z_PARAM_PATH(proto, proto_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
serv = getservbyport(htons((unsigned short) port), proto);
|
||||
@@ -2332,7 +2332,7 @@ PHP_FUNCTION(getprotobyname)
|
||||
struct protoent *ent;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
- Z_PARAM_STRING(name, name_len)
|
||||
+ Z_PARAM_PATH(name, name_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
ent = getprotobyname(name);
|
||||
diff --git a/ext/standard/dns.c b/ext/standard/dns.c
|
||||
index a81ae3f71fc..4b3fac8e915 100644
|
||||
--- a/ext/standard/dns.c
|
||||
+++ b/ext/standard/dns.c
|
||||
@@ -368,7 +368,7 @@ PHP_FUNCTION(dns_check_record)
|
||||
#endif
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||
- Z_PARAM_STRING(hostname, hostname_len)
|
||||
+ Z_PARAM_PATH(hostname, hostname_len)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_STRING(rectype, rectype_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
@@ -815,7 +815,7 @@ PHP_FUNCTION(dns_get_record)
|
||||
zend_bool raw = 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 5)
|
||||
- Z_PARAM_STRING(hostname, hostname_len)
|
||||
+ Z_PARAM_PATH(hostname, hostname_len)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(type_param)
|
||||
Z_PARAM_ZVAL(authns)
|
||||
@@ -1053,7 +1053,7 @@ PHP_FUNCTION(dns_get_mx)
|
||||
#endif
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3)
|
||||
- Z_PARAM_STRING(hostname, hostname_len)
|
||||
+ Z_PARAM_PATH(hostname, hostname_len)
|
||||
Z_PARAM_ZVAL(mx_list)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL(weight_list)
|
||||
diff --git a/ext/standard/dns_win32.c b/ext/standard/dns_win32.c
|
||||
index d677da0c150..1870998ef1f 100644
|
||||
--- a/ext/standard/dns_win32.c
|
||||
+++ b/ext/standard/dns_win32.c
|
||||
@@ -48,7 +48,7 @@ PHP_FUNCTION(dns_get_mx) /* {{{ */
|
||||
DNS_STATUS status; /* Return value of DnsQuery_A() function */
|
||||
PDNS_RECORD pResult, pRec; /* Pointer to DNS_RECORD structure */
|
||||
|
||||
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) {
|
||||
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "pz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ PHP_FUNCTION(dns_check_record)
|
||||
DNS_STATUS status; /* Return value of DnsQuery_A() function */
|
||||
PDNS_RECORD pResult; /* Pointer to DNS_RECORD structure */
|
||||
|
||||
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &hostname, &hostname_len, &rectype, &rectype_len) == FAILURE) {
|
||||
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s", &hostname, &hostname_len, &rectype, &rectype_len) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ PHP_FUNCTION(dns_get_record)
|
||||
int type, type_to_fetch, first_query = 1, store_results = 1;
|
||||
zend_bool raw = 0;
|
||||
|
||||
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lz!z!b",
|
||||
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|lz!z!b",
|
||||
&hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
diff --git a/ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt b/ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt
|
||||
new file mode 100644
|
||||
index 00000000000..3d082c8e952
|
||||
--- /dev/null
|
||||
+++ b/ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt
|
||||
@@ -0,0 +1,62 @@
|
||||
+--TEST--
|
||||
+GHSA-www2-q4fc-65wf
|
||||
+--DESCRIPTION--
|
||||
+This is a ZPP test but *keep* this as it is security-sensitive!
|
||||
+--FILE--
|
||||
+<?php
|
||||
+try {
|
||||
+ dns_check_record("\0");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ dns_get_mx("\0", $out);
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ dns_get_record("\0");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ getprotobyname("\0");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ getservbyname("\0", "tcp");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ getservbyname("x", "tcp\0");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ getservbyport(0, "tcp\0");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ inet_pton("\0");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+try {
|
||||
+ ip2long("\0");
|
||||
+} catch (ValueError $e) {
|
||||
+ echo $e->getMessage(), "\n";
|
||||
+}
|
||||
+?>
|
||||
+--EXPECT--
|
||||
+dns_check_record(): Argument #1 ($hostname) must not contain any null bytes
|
||||
+dns_get_mx(): Argument #1 ($hostname) must not contain any null bytes
|
||||
+dns_get_record(): Argument #1 ($hostname) must not contain any null bytes
|
||||
+getprotobyname(): Argument #1 ($protocol) must not contain any null bytes
|
||||
+getservbyname(): Argument #1 ($service) must not contain any null bytes
|
||||
+getservbyname(): Argument #2 ($protocol) must not contain any null bytes
|
||||
+getservbyport(): Argument #2 ($protocol) must not contain any null bytes
|
||||
+inet_pton(): Argument #1 ($ip) must not contain any null bytes
|
||||
+ip2long(): Argument #1 ($ip) must not contain any null bytes
|
||||
--
|
||||
2.52.0
|
||||
|
||||
From 52b3bdaa74078e4ea8abd9696cdbdc35a8091446 Mon Sep 17 00:00:00 2001
|
||||
From: Remi Collet <remi@remirepo.net>
|
||||
Date: Thu, 18 Dec 2025 07:17:43 +0100
|
||||
Subject: [PATCH 5/5] NEWS from 8.1.34
|
||||
|
||||
---
|
||||
NEWS | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/NEWS b/NEWS
|
||||
index c813f4f357a..ee3b272dfc6 100644
|
||||
--- a/NEWS
|
||||
+++ b/NEWS
|
||||
@@ -1,6 +1,16 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
|
||||
+Backported from 8.1.34
|
||||
+
|
||||
+- Standard:
|
||||
+ . Fixed GHSA-www2-q4fc-65wf (Null byte termination in dns_get_record()).
|
||||
+ (ndossche)
|
||||
+ . Fixed GHSA-h96m-rvf9-jgm2 (Heap buffer overflow in array_merge()).
|
||||
+ (CVE-2025-14178) (ndossche)
|
||||
+ . Fixed GHSA-3237-qqm7-mfv7 (Information Leak of Memory in getimagesize).
|
||||
+ (CVE-2025-14177) (ndossche)
|
||||
+
|
||||
Backported from 8.1.33
|
||||
|
||||
- PGSQL:
|
||||
--
|
||||
2.52.0
|
||||
|
||||
16
php.spec
16
php.spec
@ -62,7 +62,7 @@
|
||||
Summary: PHP scripting language for creating dynamic web sites
|
||||
Name: php
|
||||
Version: %{upver}%{?rcver:~%{rcver}}
|
||||
Release: 4%{?dist}
|
||||
Release: 5%{?dist}
|
||||
# All files licensed under PHP version 3.01, except
|
||||
# Zend is licensed under Zend
|
||||
# TSRM is licensed under BSD
|
||||
@ -151,6 +151,9 @@ Patch217: php-cve-2025-1219.patch
|
||||
Patch218: php-cve-2025-6491.patch
|
||||
Patch219: php-cve-2025-1220.patch
|
||||
Patch220: php-cve-2025-1735.patch
|
||||
Patch221: php-cve-2025-14177.patch
|
||||
Patch222: php-cve-2025-14178.patch
|
||||
Patch223: php-ghsa-www2-q4fc-65wf.patch
|
||||
|
||||
# Fixes for tests (300+)
|
||||
# Factory is droped from system tzdata
|
||||
@ -776,6 +779,9 @@ rm ext/openssl/tests/p12_with_extra_certs.p12
|
||||
%patch -P218 -p1 -b .cve6491
|
||||
%patch -P219 -p1 -b .cve1220
|
||||
%patch -P220 -p1 -b .cve1735
|
||||
%patch -P221 -p1 -b .cve14177
|
||||
%patch -P222 -p1 -b .cve14178
|
||||
%patch -P223 -p1 -b .ghsawwww2
|
||||
|
||||
# Fixes for tests
|
||||
%patch -P300 -p1 -b .datetests
|
||||
@ -1584,6 +1590,14 @@ systemctl try-restart php-fpm.service >/dev/null 2>&1 || :
|
||||
|
||||
|
||||
%changelog
|
||||
* Fri Jan 16 2026 Remi Collet <rcollet@redhat.com> - 8.0.30-5
|
||||
- Fix Null byte termination in dns_get_record()
|
||||
GHSA-www2-q4fc-65wf
|
||||
- Fix Heap buffer overflow in array_merge()
|
||||
CVE-2025-14178
|
||||
- Fix Information Leak of Memory in getimagesize
|
||||
CVE-2025-14177
|
||||
|
||||
* Fri Oct 3 2025 Remi Collet <rcollet@redhat.com> - 8.0.30-4
|
||||
- Fix pgsql extension does not check for errors during escaping
|
||||
CVE-2025-1735
|
||||
|
||||
Loading…
Reference in New Issue
Block a user