From aeaf48ca0bceba42b9595dff30d9e96029c54613 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka 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-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$responses = $tester + ->multiRequest([ + ['uri' => '/', 'query' => ''], + ['uri' => '/status', 'query' => 'full&html', 'delay' => 100000], + ]); +var_dump(strpos($responses[1]->getBody(), '