- Fix XSS within status endpoint CVE-2026-6735 - 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-181020
141 lines
4.3 KiB
Diff
141 lines
4.3 KiB
Diff
From aeaf48ca0bceba42b9595dff30d9e96029c54613 Mon Sep 17 00:00:00 2001
|
|
From: Jakub Zelenka <bukka@php.net>
|
|
Date: Sun, 3 May 2026 20:01:41 +0200
|
|
Subject: [PATCH 4/9] 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)
|
|
(cherry picked from commit 62daef7b73108ceda2545862cde0673f252ba2d2)
|
|
---
|
|
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 de8db9d61a2..9926ebd6b27 100644
|
|
--- a/sapi/fpm/fpm/fpm_status.c
|
|
+++ b/sapi/fpm/fpm/fpm_status.c
|
|
@@ -483,8 +483,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;
|
|
#ifdef HAVE_FPM_LQ
|
|
float cpu;
|
|
@@ -511,13 +511,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(
|
|
+ (unsigned char*)proc.request_uri,
|
|
+ strlen(proc.request_uri), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT,
|
|
+ NULL, /* double_encode */ 1);
|
|
+ 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((unsigned char *)proc.query_string, strlen(proc.query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1);
|
|
+ tmp_query_string = php_escape_html_entities_ex(
|
|
+ (unsigned char*)proc.query_string,
|
|
+ strlen(proc.query_string), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT,
|
|
+ NULL, /* double_encode */ 1);
|
|
query_string = ZSTR_VAL(tmp_query_string);
|
|
}
|
|
}
|
|
@@ -545,7 +562,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,
|
|
@@ -558,6 +575,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 00000000000..475bc130a42
|
|
--- /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
|
|
|