secret = $random->name(8, TRUE); $this->settings = [ 'directory' => $this->directory, 'bin' => 'test', 'secret' => $this->secret, ]; } /** * Tests basic load/save/delete operations. * * @covers ::load * @covers ::save * @covers ::delete * @covers ::exists */ public function testCRUD() { $php = new $this->storageClass($this->settings); $this->assertCRUD($php); } /** * Tests the security of the MTimeProtectedFileStorage implementation. * * We test two attacks: first changes the file mtime, then the directory * mtime too. * * We need to delay over 1 second for mtime test. * @medium */ public function testSecurity() { $php = new $this->storageClass($this->settings); $name = 'simpletest.php'; $php->save($name, 'directory . '/test'; if (substr($name, -4) === '.php') { $expected_directory = $expected_root_directory . '/' . substr($name, 0, -4); } else { $expected_directory = $expected_root_directory . '/' . $name; } $directory_mtime = filemtime($expected_directory); $expected_filename = $expected_directory . '/' . Crypt::hmacBase64($name, $this->secret . $directory_mtime) . '.php'; // Ensure the file exists and that it and the containing directory have // minimal permissions. fileperms() can return high bits unrelated to // permissions, so mask with 0777. $this->assertTrue(file_exists($expected_filename)); $this->assertSame(0444, fileperms($expected_filename) & 0777); $this->assertSame(0777, fileperms($expected_directory) & 0777); // Ensure the root directory for the bin has a .htaccess file denying web // access. $this->assertSame(file_get_contents($expected_root_directory . '/.htaccess'), call_user_func([$this->storageClass, 'htaccessLines'])); // Ensure that if the file is replaced with an untrusted one (due to another // script's file upload vulnerability), it does not get loaded. Since mtime // granularity is 1 second, we cannot prevent an attack that happens within // a second of the initial save(). sleep(1); for ($i = 0; $i < 2; $i++) { $php = new $this->storageClass($this->settings); $GLOBALS['hacked'] = FALSE; $untrusted_code = "assertSame(file_get_contents($expected_filename), $untrusted_code); $this->assertSame($this->expected[$i], $php->exists($name)); $this->assertSame($this->expected[$i], $php->load($name)); $this->assertSame($this->expected[$i], $GLOBALS['hacked']); } unset($GLOBALS['hacked']); } }