[Security] dont do nested calls to serialize()

This commit is contained in:
Nicolas Grekas 2019-01-25 17:59:48 +01:00
parent afb7bb5dde
commit 41000f1de0
10 changed files with 38 additions and 19 deletions

View File

@ -134,17 +134,16 @@ abstract class AbstractToken implements TokenInterface
/**
* {@inheritdoc}
*
* @param bool $isCalledFromOverridingMethod Must be set to true when called from an overriding method
*
* @return string|array Returns an array when $isCalledFromOverridingMethod is set to true
*/
public function serialize()
{
return serialize(
[
\is_object($this->user) ? clone $this->user : $this->user,
$this->authenticated,
array_map(function ($role) { return clone $role; }, $this->roles),
$this->attributes,
]
);
$serialized = [$this->user, $this->authenticated, $this->roles, $this->attributes];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
}
/**
@ -152,7 +151,7 @@ abstract class AbstractToken implements TokenInterface
*/
public function unserialize($serialized)
{
list($this->user, $this->authenticated, $this->roles, $this->attributes) = unserialize($serialized);
list($this->user, $this->authenticated, $this->roles, $this->attributes) = \is_array($serialized) ? $serialized : unserialize($serialized);
}
/**
@ -232,6 +231,19 @@ abstract class AbstractToken implements TokenInterface
return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles));
}
/**
* @internal
*/
protected function doSerialize($serialized, $isCalledFromOverridingMethod)
{
if (null === $isCalledFromOverridingMethod) {
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 3);
$isCalledFromOverridingMethod = isset($trace[2]['function'], $trace[2]['object']) && 'serialize' === $trace[2]['function'] && $this === $trace[2]['object'];
}
return $isCalledFromOverridingMethod ? $serialized : serialize($serialized);
}
private function hasUserChanged(UserInterface $user)
{
if (!($this->user instanceof UserInterface)) {

View File

@ -67,7 +67,7 @@ class AnonymousToken extends AbstractToken
*/
public function unserialize($serialized)
{
list($this->secret, $parentStr) = unserialize($serialized);
list($this->secret, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized);
parent::unserialize($parentStr);
}
}

View File

@ -76,10 +76,14 @@ class PreAuthenticatedToken extends AbstractToken
/**
* {@inheritdoc}
*
* @param bool $isCalledFromOverridingMethod Must be set to true when called from an overriding method
*/
public function serialize()
{
return serialize([$this->credentials, $this->providerKey, parent::serialize()]);
$serialized = [$this->credentials, $this->providerKey, parent::serialize(true)];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
}
/**
@ -87,7 +91,7 @@ class PreAuthenticatedToken extends AbstractToken
*/
public function unserialize($str)
{
list($this->credentials, $this->providerKey, $parentStr) = unserialize($str);
list($this->credentials, $this->providerKey, $parentStr) = \is_array($str) ? $str : unserialize($str);
parent::unserialize($parentStr);
}
}

View File

@ -106,7 +106,7 @@ class RememberMeToken extends AbstractToken
*/
public function unserialize($serialized)
{
list($this->secret, $this->providerKey, $parentStr) = unserialize($serialized);
list($this->secret, $this->providerKey, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized);
parent::unserialize($parentStr);
}
}

View File

@ -99,7 +99,7 @@ class UsernamePasswordToken extends AbstractToken
*/
public function unserialize($serialized)
{
list($this->credentials, $this->providerKey, $parentStr) = unserialize($serialized);
list($this->credentials, $this->providerKey, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized);
parent::unserialize($parentStr);
}
}

View File

@ -55,7 +55,7 @@ abstract class AccountStatusException extends AuthenticationException
*/
public function unserialize($str)
{
list($this->user, $parentData) = unserialize($str);
list($this->user, $parentData) = \is_array($str) ? $str : unserialize($str);
parent::unserialize($parentData);
}

View File

@ -72,7 +72,7 @@ class CustomUserMessageAuthenticationException extends AuthenticationException
*/
public function unserialize($str)
{
list($parentData, $this->messageKey, $this->messageData) = unserialize($str);
list($parentData, $this->messageKey, $this->messageData) = \is_array($str) ? $str : unserialize($str);
parent::unserialize($parentData);
}

View File

@ -65,7 +65,7 @@ class UsernameNotFoundException extends AuthenticationException
*/
public function unserialize($str)
{
list($this->username, $parentData) = unserialize($str);
list($this->username, $parentData) = \is_array($str) ? $str : unserialize($str);
parent::unserialize($parentData);
}

View File

@ -43,6 +43,9 @@ class ConcreteToken extends AbstractToken
$this->setUser($user);
}
/**
* @param bool $isCalledFromOverridingMethod Must be set to true when called from an overriding method
*/
public function serialize()
{
return serialize([$this->credentials, parent::serialize()]);

View File

@ -76,7 +76,7 @@ class PostAuthenticationGuardToken extends AbstractToken implements GuardTokenIn
*/
public function serialize()
{
return serialize([$this->providerKey, parent::serialize()]);
return serialize([$this->providerKey, parent::serialize(true)]);
}
/**
@ -84,7 +84,7 @@ class PostAuthenticationGuardToken extends AbstractToken implements GuardTokenIn
*/
public function unserialize($serialized)
{
list($this->providerKey, $parentStr) = unserialize($serialized);
list($this->providerKey, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized);
parent::unserialize($parentStr);
}
}