diff --git a/book/security.rst b/book/security.rst index fbe468213ef..ae2456668c5 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1410,6 +1410,13 @@ can always be determined in the following way from a controller:: $password = $encoder->encodePassword('ryanpass', $user->getSalt()); $user->setPassword($password); +.. caution:: + + When you allow a user to submit a plaintext password (e.g. registration + form, change password form), you *must* have validation that guarantees + that the password is 4096 characters or less. Read more details in + :ref:`How to implement a simple Registration Form `. + Retrieving the User Object ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/components/security/authentication.rst b/components/security/authentication.rst index 9af8c9265c9..016dde98c46 100644 --- a/components/security/authentication.rst +++ b/components/security/authentication.rst @@ -190,8 +190,21 @@ Each encoder should implement :class:`Symfony\\Component\\Security\\Core\\Encode or be an array with a ``class`` and an ``arguments`` key, which allows the encoder factory to construct the encoder only when it is needed. -Password Encoders -~~~~~~~~~~~~~~~~~ +Creating a Custom Password Encoder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are many built-in password encoders. But if you need to create your +own, it just needs to follow these rules: + +#. The class must implement :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`; + +#. The first line in ``encodePassword`` and ``isPasswordValid`` must check + to make sure the password is not too long (e.g. 4096). This is for security + (see `CVE-2013-5750`_), and you can copy the `BasePasswordEncoder::checkPasswordLength`_ + implementation from Symfony 2.4. + +Using Password Encoders +~~~~~~~~~~~~~~~~~~~~~~~ When the :method:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactory::getEncoder` method of the password encoder factory is called with the user object as @@ -213,3 +226,6 @@ which should be used to encode this user's password:: $user->getPassword(), $password, $user->getSalt()); + +.. _`CVE-2013-5750`: http://symfony.com/blog/cve-2013-5750-security-issue-in-fosuserbundle-login-form +.. _`BasePasswordEncoder::checkPasswordLength`: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.php \ No newline at end of file diff --git a/cookbook/doctrine/registration_form.rst b/cookbook/doctrine/registration_form.rst index e274cf1c639..8d9b4b3ff16 100644 --- a/cookbook/doctrine/registration_form.rst +++ b/cookbook/doctrine/registration_form.rst @@ -45,6 +45,7 @@ You have a simple ``User`` entity mapped to the database:: /** * @ORM\Column(type="string", length=255) * @Assert\NotBlank() + * @Assert\Length(max = 4096) */ protected $plainPassword; @@ -85,6 +86,21 @@ the class. to implement the :ref:`UserInterface` of the security component. +.. _cookbook-registration-password-max: + +.. sidebar:: Why the 4096 Password Limit? + + Notice that the ``plainPassword`` has a max length of ``4096`` characters. + For security purposes (`CVE-2013-5750`_), Symfony limits the plain password + length to 4096 characters when encoding it. Adding this constraint makes + sure that your form will give a validation error if anyone tries a super-long + password. + + You'll need to add this constraint anywhere in your application where + your user submits a plaintext password (e.g. change password form). The + only place where you don't need to worry about this is your login form, + since Symfony's Security component handles this for you. + Create a Form for the Model --------------------------- @@ -346,3 +362,5 @@ That's it! Your form now validates, and allows you to save the ``User`` object to the database. The extra ``terms`` checkbox on the ``Registration`` model class is used during validation, but not actually used afterwards when saving the User to the database. + +.. _`CVE-2013-5750`: http://symfony.com/blog/cve-2013-5750-security-issue-in-fosuserbundle-login-form