@ZaphodB fix(security): ?/Test integrity diagnostics answered without a login

ServiceTest() ran Integrity::test() for any request. The test builds its base
URL from $_SERVER['HTTP_HOST'], sends HEAD requests to it and prints the status
and every response header. The client therefore chose where the server sent
requests and read the result. Behind nginx the vhost is picked by server_name
with the port ignored, so Host: <this host>:<port> reaches the app and turns the
diagnostic into a probe of the server's own TLS ports and their headers.

Answer 404 unless an admin session is present. An admin's browser sends the
real Host, so the diagnostic still works for the people it is for.

Checked end to end with php -S (4 workers, no network): without a session the
old code returned 200 with the diagnostics, this one returns 404 and nothing.
This commit is contained in:
djmaze 2026-10-25 23:42:42 +01:00
parent 7f1b1e6288
commit bf0aa84fe7

View file

@ -10,6 +10,16 @@ abstract class Integrity
*/ */
public static function test() public static function test()
{ {
// The integrity test sends HEAD requests to a URL built from the request's
// Host header and prints back every response header. Open to anyone, that
// lets a client choose the target (nginx ignores the port when matching
// server_name, so Host: <this host>:<port> reaches it) and read the result.
// It is an admin diagnostic; an admin's own browser sends the real Host.
if (!\RainLoop\Api::Actions()->IsAdminLoggined(false)) {
\MailSo\Base\Http::StatusHeader(404);
return '';
}
$result = static::phpVersion(); $result = static::phpVersion();
if ($result) { if ($result) {
echo '<p style="color: red">' . $result . '</p>'; echo '<p style="color: red">' . $result . '</p>';