Skip to content
This repository was archived by the owner on May 31, 2024. It is now read-only.

Commit 51f245f

Browse files
MacDadafabpot
authored andcommitted
[Security] AbstractRememberMeServices::encodeCookie() validates cookie parts
1 parent c7a417a commit 51f245f

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

Http/RememberMe/AbstractRememberMeServices.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,17 @@ protected function decodeCookie($rawCookie)
268268
* @param array $cookieParts
269269
*
270270
* @return string
271+
*
272+
* @throws \InvalidArgumentException When $cookieParts contain the cookie delimiter. Extending class should either remove or escape it.
271273
*/
272274
protected function encodeCookie(array $cookieParts)
273275
{
276+
foreach ($cookieParts as $cookiePart) {
277+
if (false !== strpos($cookiePart, self::COOKIE_DELIMITER)) {
278+
throw new \InvalidArgumentException(sprintf('$cookieParts should not contain the cookie delimiter "%s"', self::COOKIE_DELIMITER));
279+
}
280+
}
281+
274282
return base64_encode(implode(self::COOKIE_DELIMITER, $cookieParts));
275283
}
276284

Http/RememberMe/TokenBasedRememberMeServices.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,6 @@ protected function onLoginSuccess(Request $request, Response $response, TokenInt
119119
* @param int $expires The Unix timestamp when the cookie expires
120120
* @param string $password The encoded password
121121
*
122-
* @throws \RuntimeException if username contains invalid chars
123-
*
124122
* @return string
125123
*/
126124
protected function generateCookieValue($class, $username, $expires, $password)
@@ -141,8 +139,6 @@ protected function generateCookieValue($class, $username, $expires, $password)
141139
* @param int $expires The Unix timestamp when the cookie expires
142140
* @param string $password The encoded password
143141
*
144-
* @throws \RuntimeException when the private key is empty
145-
*
146142
* @return string
147143
*/
148144
protected function generateCookieHash($class, $username, $expires, $password)

Tests/Http/RememberMe/AbstractRememberMeServicesTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
1515
use Symfony\Component\HttpFoundation\Request;
1616
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices;
1718

1819
class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
1920
{
@@ -236,6 +237,30 @@ public function getPositiveRememberMeParameterValues()
236237
);
237238
}
238239

240+
public function testEncodeCookieAndDecodeCookieAreInvertible()
241+
{
242+
$cookieParts = array('aa', 'bb', 'cc');
243+
$service = $this->getService();
244+
245+
$encoded = $this->callProtected($service, 'encodeCookie', array($cookieParts));
246+
$this->assertInternalType('string', $encoded);
247+
248+
$decoded = $this->callProtected($service, 'decodeCookie', array($encoded));
249+
$this->assertSame($cookieParts, $decoded);
250+
}
251+
252+
/**
253+
* @expectedException InvalidArgumentException
254+
* @expectedExceptionMessage cookie delimiter
255+
*/
256+
public function testThereShouldBeNoCookieDelimiterInCookieParts()
257+
{
258+
$cookieParts = array('aa', 'b'.AbstractRememberMeServices::COOKIE_DELIMITER.'b', 'cc');
259+
$service = $this->getService();
260+
261+
$this->callProtected($service, 'encodeCookie', array($cookieParts));
262+
}
263+
239264
protected function getService($userProvider = null, $options = array(), $logger = null)
240265
{
241266
if (null === $userProvider) {
@@ -258,4 +283,13 @@ protected function getProvider()
258283

259284
return $provider;
260285
}
286+
287+
private function callProtected($object, $method, array $args)
288+
{
289+
$reflection = new \ReflectionClass(get_class($object));
290+
$reflectionMethod = $reflection->getMethod($method);
291+
$reflectionMethod->setAccessible(true);
292+
293+
return $reflectionMethod->invokeArgs($object, $args);
294+
}
261295
}

0 commit comments

Comments
 (0)