php/php-cve-2026-6735.patch
Remi Collet e6ee411f95 Fix CVEs up to 8.2.31:
- Fix XSS within status endpoint  CVE-2026-6735
- Fix Null pointer dereference in php_mb_check_encoding() via mb_ereg_search_init()  CVE-2026-7259
- Fix Stale SOAP_GLOBAL(ref_map) pointer with Apache Map  CVE-2026-6722
- Fix Use-after-free after header parsing failure with SOAP_PERSISTENCE_SESSION  CVE-2026-7261
- Fix Broken Apache map value NULL check  CVE-2026-7262
- Fix Signed integer overflow of char array offset  CVE-2026-7568
- Fix Consistently pass unsigned char to ctype.h functions  CVE-2026-7258

Resolves: RHEL-181025
2026-06-05 15:11:53 +02:00

140 lines
4.3 KiB
Diff

From 62daef7b73108ceda2545862cde0673f252ba2d2 Mon Sep 17 00:00:00 2001
From: Jakub Zelenka <bukka@php.net>
Date: Sun, 3 May 2026 20:01:41 +0200
Subject: [PATCH 04/10] GHSA-7qg2-v9fj-4mwv: [fpm] XSS within status endpoint
Fixes GHSA-7qg2-v9fj-4mwv
Fixes CVE-2026-6735
(cherry picked from commit 99a5ad7441de9914246c7863adb6997396008b9d)
(cherry picked from commit cc2960e782eb5cc262d7bd572a7d18979a811954)
---
sapi/fpm/fpm/fpm_status.c | 28 +++++++++--
.../tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt | 48 +++++++++++++++++++
2 files changed, 72 insertions(+), 4 deletions(-)
create mode 100644 sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt
diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c
index b77c7fb700..b5e969288c 100644
--- a/sapi/fpm/fpm/fpm_status.c
+++ b/sapi/fpm/fpm/fpm_status.c
@@ -448,8 +448,8 @@ int fpm_status_handle_request(void) /* {{{ */
if (full_syntax) {
unsigned int i;
int first;
- zend_string *tmp_query_string;
- char *query_string;
+ zend_string *tmp_query_string, *tmp_request_uri_string;
+ char *query_string, *request_uri_string;
struct timeval duration, now;
float cpu;
@@ -474,13 +474,30 @@ int fpm_status_handle_request(void) /* {{{ */
}
}
+ request_uri_string = NULL;
+ tmp_request_uri_string = NULL;
+ if (proc->request_uri[0] != '\0') {
+ if (encode) {
+ tmp_request_uri_string = php_escape_html_entities_ex(
+ (const unsigned char *) proc->request_uri,
+ strlen(proc->request_uri), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT,
+ NULL, /* double_encode */ 1, /* quiet */ 0);
+ request_uri_string = ZSTR_VAL(tmp_request_uri_string);
+ } else {
+ request_uri_string = proc->request_uri;
+ }
+ }
+
query_string = NULL;
tmp_query_string = NULL;
if (proc->query_string[0] != '\0') {
if (!encode) {
query_string = proc->query_string;
} else {
- tmp_query_string = php_escape_html_entities_ex((const unsigned char *) proc->query_string, strlen(proc->query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, /* double_encode */ 1, /* quiet */ 0);
+ tmp_query_string = php_escape_html_entities_ex(
+ (const unsigned char *) proc->query_string,
+ strlen(proc->query_string), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT,
+ NULL, /* double_encode */ 1, /* quiet */ 0);
query_string = ZSTR_VAL(tmp_query_string);
}
}
@@ -506,7 +523,7 @@ int fpm_status_handle_request(void) /* {{{ */
proc->requests,
duration.tv_sec * 1000000UL + duration.tv_usec,
proc->request_method[0] != '\0' ? proc->request_method : "-",
- proc->request_uri[0] != '\0' ? proc->request_uri : "-",
+ request_uri_string ? request_uri_string : "-",
query_string ? "?" : "",
query_string ? query_string : "",
proc->content_length,
@@ -517,6 +534,9 @@ int fpm_status_handle_request(void) /* {{{ */
PUTS(buffer);
efree(buffer);
+ if (tmp_request_uri_string) {
+ zend_string_free(tmp_request_uri_string);
+ }
if (tmp_query_string) {
zend_string_free(tmp_query_string);
}
diff --git a/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt
new file mode 100644
index 0000000000..475bc130a4
--- /dev/null
+++ b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt
@@ -0,0 +1,48 @@
+--TEST--
+FPM: GHSA-7qg2-v9fj-4mwv - status xss
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+require_once "tester.inc";
+
+$cfg = <<<EOT
+[global]
+error_log = {{FILE:LOG}}
+[unconfined]
+listen = {{ADDR}}
+pm = static
+pm.max_children = 2
+pm.status_path = /status
+catch_workers_output = yes
+EOT;
+
+$code = <<<EOT
+<?php
+usleep(200000);
+EOT;
+
+$tester = new FPM\Tester($cfg, $code);
+$tester->start();
+$tester->expectLogStartNotices();
+$responses = $tester
+ ->multiRequest([
+ ['uri' => '/<script>alert(1)</script>', 'query' => '<script>alert(2)</script>'],
+ ['uri' => '/status', 'query' => 'full&html', 'delay' => 100000],
+ ]);
+var_dump(strpos($responses[1]->getBody(), '<script>'));
+$tester->terminate();
+$tester->expectLogTerminatingNotices();
+$tester->close();
+
+?>
+Done
+--EXPECT--
+bool(false)
+Done
+--CLEAN--
+<?php
+require_once "tester.inc";
+FPM\Tester::clean();
+?>
--
2.54.0