Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f2d687a

Browse filesBrowse files
committed
feature #25669 [Security] Fail gracefully if the security token cannot be unserialized from the session (thewilkybarkid)
This PR was merged into the 2.7 branch. Discussion ---------- [Security] Fail gracefully if the security token cannot be unserialized from the session | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | If the security token in the session can't be unserialized, an `E_NOTICE` is issued. This prevents it (and provides a better log message if it's not even a `__PHP_Incomplete_Class`). This is similar to #24731, but I saw it triggered when changing OAuth library (elifesciences/journal#824), so the token class itself no longer exists. (I want to avoid having to manually invalidate all sessions, as not all sessions use that token class.) Commits ------- 053fa43 [Security] Fail gracefully if the security token cannot be unserialized from the session
2 parents 813f957 + 053fa43 commit f2d687a
Copy full SHA for f2d687a

File tree

2 files changed

+44
-1
lines changed
Filter options

2 files changed

+44
-1
lines changed

‎src/Symfony/Component/Security/Http/Firewall/ContextListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Firewall/ContextListener.php
+42-1Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class ContextListener implements ListenerInterface
3939
private $dispatcher;
4040
private $registered;
4141

42+
private static $unserializeExceptionCode = 0x37313bc;
43+
4244
public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
4345
{
4446
if (empty($contextKey)) {
@@ -77,7 +79,7 @@ public function handle(GetResponseEvent $event)
7779
return;
7880
}
7981

80-
$token = unserialize($token);
82+
$token = $this->safelyUnserialize($token);
8183

8284
if (null !== $this->logger) {
8385
$this->logger->debug('Read existing security token from the session.', array('key' => $this->sessionKey));
@@ -171,4 +173,43 @@ protected function refreshUser(TokenInterface $token)
171173

172174
throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user)));
173175
}
176+
177+
private function safelyUnserialize($serializedToken)
178+
{
179+
$e = $token = null;
180+
$prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
181+
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$prevErrorHandler) {
182+
if (__FILE__ === $file) {
183+
throw new \UnexpectedValueException($msg, self::$unserializeExceptionCode);
184+
}
185+
186+
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
187+
});
188+
189+
try {
190+
$token = unserialize($serializedToken);
191+
} catch (\Error $e) {
192+
} catch (\Exception $e) {
193+
}
194+
restore_error_handler();
195+
ini_set('unserialize_callback_func', $prevUnserializeHandler);
196+
if ($e) {
197+
if (!$e instanceof \UnexpectedValueException || self::$unserializeExceptionCode !== $e->getCode()) {
198+
throw $e;
199+
}
200+
if ($this->logger) {
201+
$this->logger->warning('Failed to unserialize the security token from the session.', array('key' => $this->sessionKey, 'received' => $serializedToken, 'exception' => $e));
202+
}
203+
}
204+
205+
return $token;
206+
}
207+
208+
/**
209+
* @internal
210+
*/
211+
public static function handleUnserializeCallback($class)
212+
{
213+
throw new \UnexpectedValueException('Class not found: '.$class, self::$unserializeExceptionCode);
214+
}
174215
}

‎src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ public function testInvalidTokenInSession($token)
169169
public function provideInvalidToken()
170170
{
171171
return array(
172+
array('foo'),
173+
array('O:8:"NotFound":0:{}'),
172174
array(serialize(new \__PHP_Incomplete_Class())),
173175
array(serialize(null)),
174176
array(null),

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.