Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 053fa43

Browse files
thewilkybarkidnicolas-grekas
authored andcommitted
[Security] Fail gracefully if the security token cannot be unserialized from the session
1 parent 05adcd0 commit 053fa43

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

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

Lines 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

Lines 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)