diff --git a/display.php b/display.php index 37ad0c8..e76680a 100644 --- a/display.php +++ b/display.php @@ -5,6 +5,8 @@ require_once('./get_data.lib.php'); $queue = get_queue(); if ($queue) session_cache_limiter('nocache'); else session_cache_limiter('none'); +// Refuse a session id that PHP did not make, so nobody can plant one +ini_set('session.use_strict_mode', '1'); session_set_cookie_params(array('lifetime' => 0, 'path' => '/', 'domain' => cookie_domain(), 'secure' => TRUE, 'httponly' => TRUE, 'samesite' => 'Lax')); session_start(); if (isset($_SESSION['editor']) && editor_exists($_SESSION['editor'])) { diff --git a/session.lib.php b/session.lib.php index 0a0d8f6..0466146 100644 --- a/session.lib.php +++ b/session.lib.php @@ -13,6 +13,8 @@ if (isset($_SERVER['HTTPS'])) { // Browsers use HTTPS for this host for a year, without a plain request first header('Strict-Transport-Security: max-age=31536000'); session_cache_limiter('private'); + // Refuse a session id that PHP did not make, so nobody can plant one + ini_set('session.use_strict_mode', '1'); session_set_cookie_params(array('lifetime' => 0, 'path' => '/', 'domain' => cookie_domain(), 'secure' => TRUE, 'httponly' => TRUE, 'samesite' => 'Lax')); session_start(); diff --git a/tests/php/Pages/FrontPagesTest.php b/tests/php/Pages/FrontPagesTest.php index 4078b40..a753275 100644 --- a/tests/php/Pages/FrontPagesTest.php +++ b/tests/php/Pages/FrontPagesTest.php @@ -57,6 +57,17 @@ class FrontPagesTest extends PageTestCase { $this->assertNull($this->header($this->get('/', array('X-Test-Plain' => '1')), 'Strict-Transport-Security')); } + // PHP makes a new id for a session id that it did not make, so nobody can plant one + public function testAnUnknownSessionIdIsReplaced(): void { + $planted = str_repeat('ab', 16); + foreach (array('/', '/display?id=1') as $path) { + $this->cookies = array('PHPSESSID' => $planted); + $this->get($path); + $this->assertNotSame($planted, $this->cookies['PHPSESSID'] ?? NULL, $path); + $this->assertFileDoesNotExist(self::$state . "/sessions/sess_$planted", $path); + } + } + public function testPlainHttpStartsNoSession(): void { $page = $this->get('/', array('X-Test-Plain' => '1')); $this->assertSame(200, $page['status']);