CVE-2013-5750: Security issue in FOSUserBundle login form

Django recently released a new version of their framework to address a possible DOS attack when an attacker uses a very long password on a login form.

One of the best practices for passwords is to store a hash of the password instead of the raw value. In Symfony, the encoders are responsible for the hash creation (when a user creates an account) and verification (when a user tries to log in).

For most built-in encoders, the time is takes to compute a hash increases significantly with the length of the password. If an attacker submits random large passwords repeatedly, Symfony will be forced to do expensive computation.

All encoders are not vulnerable, but the recommended ones are. For information, here are the times it takes to encode a password of 1 million characters (lines with a * denotes the built-in encoder default configurations):

Encoder encodePassword()
BCrypt (cost <14) <1s
BCrypt (cost 18) 20s
BCrypt (cost 20) 78s
Pbkdf2* (1,000 it) 6s
Plaintext* <1s
MessageDigest* (5,000 it) 30s
Pbkdf2 (10,000 it) 55s

As you can see, for the Pbkdf2 encoder, it takes almost one minute when the number of iterations is set to 10,000 (which is the number of iterations used in iOS 7.)

Symfony does not come with a default login/password form, but FOSUserBundle does. FOSUserBundle is vulnerable to this attack as there is no password length maximum in the validation for the user password field. A new version of FOSUserBundle (1.3.3) has just been released to fix this issue by adding a maximum length for a valid password (set to 4096 by default). If your website uses a login form without using FOSUserBundle, check that you set a max length validator for the password.

To better protect Symfony developers, Symfony 2.4 adds a hard limit of 4096 characters for the maximum length of a password passed to the encodePassword() and isPasswordValid() methods (you need to call $this->checkPasswordLength($raw); yourself if you have using a custom encoder). So, you need to set the maximum length of your validator to the same or lower limit.

We are also going to update the documentation with updated best practices about passwords and encoders.

If you have found a security issue in Symfony, please send the details to security [at] symfony.com and don't disclose it publicly until we can provide a fix for it.

Comments

Thx!
To be clear, the FOSUserBundle fix is protecting the signup and profile edition forms (where the plain password is hashed before being saved) and forbids legitimate password to be longer than 4096 chars.

The handling of the login form is not implemented by FOSUserBundle (it only displays a form) but by the Symfony Security component, and the way to avoid a DOS attack on the login form is the hard limit implemented in Symfony.
So developers using 2.3 without FOSUserBundle should manually add a password length check?
@Arnaud even with FOSUserBundle, the max length in the encoder should still be needed, as explained in my comment #2.

The max length set in FOSUserBundle has 2 use cases:
- protecting the signup and password reset forms (they are also protected by the Symfony change in 2.4 btw, as the encoder is used)
- forbidding users to set a legitimate password longer than the max length supported by Symfony (a validation error is better than a BadCredentialException when you are setting your new password)
Thanks.
So this means, 2.3 and lower logins are not protected, as the login is handled by the Symfony security component?

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.