[Security] limited the password length passed to encoders
This commit is contained in:
parent
b1542f0620
commit
f7d0ec6f4a
@ -64,6 +64,8 @@ class BCryptPasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function encodePassword($raw, $salt)
|
public function encodePassword($raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
$options = array('cost' => $this->cost);
|
$options = array('cost' => $this->cost);
|
||||||
|
|
||||||
if ($salt) {
|
if ($salt) {
|
||||||
@ -78,6 +80,8 @@ class BCryptPasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function isPasswordValid($encoded, $raw, $salt)
|
public function isPasswordValid($encoded, $raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
return password_verify($raw, $encoded);
|
return password_verify($raw, $encoded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\Security\Core\Encoder;
|
namespace Symfony\Component\Security\Core\Encoder;
|
||||||
|
|
||||||
use Symfony\Component\Security\Core\Util\StringUtils;
|
use Symfony\Component\Security\Core\Util\StringUtils;
|
||||||
|
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BasePasswordEncoder is the base class for all password encoders.
|
* BasePasswordEncoder is the base class for all password encoders.
|
||||||
@ -20,6 +21,8 @@ use Symfony\Component\Security\Core\Util\StringUtils;
|
|||||||
*/
|
*/
|
||||||
abstract class BasePasswordEncoder implements PasswordEncoderInterface
|
abstract class BasePasswordEncoder implements PasswordEncoderInterface
|
||||||
{
|
{
|
||||||
|
const MAX_PASSWORD_LENGTH = 4096;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demerges a merge password and salt string.
|
* Demerges a merge password and salt string.
|
||||||
*
|
*
|
||||||
@ -83,4 +86,11 @@ abstract class BasePasswordEncoder implements PasswordEncoderInterface
|
|||||||
{
|
{
|
||||||
return StringUtils::equals($password1, $password2);
|
return StringUtils::equals($password1, $password2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function checkPasswordLength($password)
|
||||||
|
{
|
||||||
|
if (strlen($password) > self::MAX_PASSWORD_LENGTH) {
|
||||||
|
throw new BadCredentialsException('Invalid password.');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@ class MessageDigestPasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function encodePassword($raw, $salt)
|
public function encodePassword($raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
if (!in_array($this->algorithm, hash_algos(), true)) {
|
if (!in_array($this->algorithm, hash_algos(), true)) {
|
||||||
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
|
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
|
||||||
}
|
}
|
||||||
@ -61,6 +63,8 @@ class MessageDigestPasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function isPasswordValid($encoded, $raw, $salt)
|
public function isPasswordValid($encoded, $raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
|
return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,8 @@ class Pbkdf2PasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function encodePassword($raw, $salt)
|
public function encodePassword($raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
if (!in_array($this->algorithm, hash_algos(), true)) {
|
if (!in_array($this->algorithm, hash_algos(), true)) {
|
||||||
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
|
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
|
||||||
}
|
}
|
||||||
@ -72,6 +74,8 @@ class Pbkdf2PasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function isPasswordValid($encoded, $raw, $salt)
|
public function isPasswordValid($encoded, $raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
|
return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ class PlaintextPasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function encodePassword($raw, $salt)
|
public function encodePassword($raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
return $this->mergePasswordAndSalt($raw, $salt);
|
return $this->mergePasswordAndSalt($raw, $salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +45,8 @@ class PlaintextPasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function isPasswordValid($encoded, $raw, $salt)
|
public function isPasswordValid($encoded, $raw, $salt)
|
||||||
{
|
{
|
||||||
|
$this->checkPasswordLength($raw);
|
||||||
|
|
||||||
$pass2 = $this->mergePasswordAndSalt($raw, $salt);
|
$pass2 = $this->mergePasswordAndSalt($raw, $salt);
|
||||||
|
|
||||||
if (!$this->ignorePasswordCase) {
|
if (!$this->ignorePasswordCase) {
|
||||||
|
@ -64,6 +64,26 @@ class BCryptPasswordEncoderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null));
|
$this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testEncodePasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new BCryptPasswordEncoder(4);
|
||||||
|
|
||||||
|
$encoder->encodePassword(str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testCheckPasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new BCryptPasswordEncoder(4);
|
||||||
|
|
||||||
|
$encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
|
|
||||||
private function skipIfPhpVersionIsNotSupported()
|
private function skipIfPhpVersionIsNotSupported()
|
||||||
{
|
{
|
||||||
if (version_compare(phpversion(), '5.3.7', '<')) {
|
if (version_compare(phpversion(), '5.3.7', '<')) {
|
||||||
|
@ -42,4 +42,24 @@ class MessageDigestPasswordEncoderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$encoder = new MessageDigestPasswordEncoder('foobar');
|
$encoder = new MessageDigestPasswordEncoder('foobar');
|
||||||
$encoder->encodePassword('password', '');
|
$encoder->encodePassword('password', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testEncodePasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new MessageDigestPasswordEncoder();
|
||||||
|
|
||||||
|
$encoder->encodePassword(str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testCheckPasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new MessageDigestPasswordEncoder();
|
||||||
|
|
||||||
|
$encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,4 +42,24 @@ class Pbkdf2PasswordEncoderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$encoder = new Pbkdf2PasswordEncoder('foobar');
|
$encoder = new Pbkdf2PasswordEncoder('foobar');
|
||||||
$encoder->encodePassword('password', '');
|
$encoder->encodePassword('password', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testEncodePasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new Pbkdf2PasswordEncoder();
|
||||||
|
|
||||||
|
$encoder->encodePassword(str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testCheckPasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new Pbkdf2PasswordEncoder();
|
||||||
|
|
||||||
|
$encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,4 +36,24 @@ class PlaintextPasswordEncoderTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertSame('foo', $encoder->encodePassword('foo', ''));
|
$this->assertSame('foo', $encoder->encodePassword('foo', ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testEncodePasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new PlaintextPasswordEncoder();
|
||||||
|
|
||||||
|
$encoder->encodePassword(str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||||
|
*/
|
||||||
|
public function testCheckPasswordLength()
|
||||||
|
{
|
||||||
|
$encoder = new PlaintextPasswordEncoder();
|
||||||
|
|
||||||
|
$encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user