You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<?php
// https://one.example.com
// possibly only with HTTP 2/3, didn't test with HTTP 1.0/1.1
if ( $_SERVER['REQUEST_URI'] === '/result/' || $_SERVER['REQUEST_URI'] === '/world/' ) {
echo "done";
exit;
}
// this is required to stop nginx from buffering the response (and otherwise this error doesn't happen)
header( 'X-Accel-Buffering: no' );
header( 'Location: https://one.example.com/result/', true, 302 );
register_shutdown_function( static function () {
register_shutdown_function( static function () {
// this is required, otherwise it won't happen
fastcgi_finish_request();
// the "sleep" is what creates the issue. A usleep for a shorter amount of time seems to be enough though (I don't think the sleep() is the origin of the issue though, it just allows other requests to be handled in the meantime, which causes this issue)
sleep( 1 );
// echoing arbitrary text with a space before any ":" will cause nginx to report:
// upstream sent invalid header: "a\x20..." while reading response header from upstream
// echo 'a b';
// outputting text that looks like a header, will set this as response header for the page we redirect to, but concatenates it randomly with a different response header (see screenshot)
echo 'X-Risky: yes';
} );
} );
When opening https://one.example.com, the echoed "X-Risky" suddenly shows up as a response header on the redirected URL, with the value randomly concatenated with another response header (actual one that the redirected request set)
If we echo something with a space before the :, e.g. echo 'a b'; nginx will instead report an error (on the redirected URL too!):
upstream sent invalid header: "a\x20..." while reading response header from upstream
What is potentially a security issue is, that it seems to apply that "X-Risky" to whatever next request is handled by nginx. Even if it is a different subdomain (didn't test it for different domain).
e.g. if I am on one.example.com (which is it's own server {} block in nginx), and set a Location: https://two.example.com (which is it's own server {} block in nginx too, but handled in the same nginx instance), then suddenly I get the X-Risky header in the response of two.example.com (and when using the "a b" I also get the upstream error in the two.example.com nginx error log)
It's not necessarily the "Location:" that this wrong header is applied too:
e.g. replace the "Location:" header in the example above with: Link: </world/>; as=fetch; crossorigin; rel=preload
when requesting the page in Chrome, the response for /world/ will suddenly have the X-Risky header
Even worse, it seems it's just whatever request is next handled by the nginx instance at the time AFTER the sleep gets that header applied (or the error reported), even if it's a completely different (sub)domain in a different server {} block
(this issue happens independent of request method, e.g. GET, POST,... all same)
The issue seems to be for responses that do not have a request body, but are headers only at the time when fastcgi_finish_request() is called.
This isn't a security issue in PHP itself (therefore not reported as such), but just an unclear and unexpected error.
It has been reported to nginx as a security advisory independently
PHP Version
PHP 8.3.17 (php-fpm) + nginx 1.27.1.1
Operating System
No response
The text was updated successfully, but these errors were encountered:
Description
When opening https://one.example.com, the echoed "X-Risky" suddenly shows up as a response header on the redirected URL, with the value randomly concatenated with another response header (actual one that the redirected request set)
If we echo something with a space before the :, e.g. echo 'a b'; nginx will instead report an error (on the redirected URL too!):
What is potentially a security issue is, that it seems to apply that "X-Risky" to whatever next request is handled by nginx. Even if it is a different subdomain (didn't test it for different domain).
e.g. if I am on one.example.com (which is it's own server {} block in nginx), and set a Location: https://two.example.com (which is it's own server {} block in nginx too, but handled in the same nginx instance), then suddenly I get the X-Risky header in the response of two.example.com (and when using the "a b" I also get the upstream error in the two.example.com nginx error log)
It's not necessarily the "Location:" that this wrong header is applied too:
e.g. replace the "Location:" header in the example above with:
Link: </world/>; as=fetch; crossorigin; rel=preload
when requesting the page in Chrome, the response for /world/ will suddenly have the X-Risky header
Even worse, it seems it's just whatever request is next handled by the nginx instance at the time AFTER the sleep gets that header applied (or the error reported), even if it's a completely different (sub)domain in a different server {} block
(this issue happens independent of request method, e.g. GET, POST,... all same)
The issue seems to be for responses that do not have a request body, but are headers only at the time when fastcgi_finish_request() is called.
I guess PHP
fastcgi_finish_request()
doesn't send an "EOF" https://github.com/openresty/lua-nginx-module?tab=readme-ov-file#ngxeofThis isn't a security issue in PHP itself (therefore not reported as such), but just an unclear and unexpected error.
It has been reported to nginx as a security advisory independently
PHP Version
PHP 8.3.17 (php-fpm) + nginx 1.27.1.1
Operating System
No response
The text was updated successfully, but these errors were encountered: