Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security] Fix BCryptPasswordEncoder to encode password using salt #8210

Closed
wants to merge 1 commit into from
Closed

[Security] Fix BCryptPasswordEncoder to encode password using salt #8210

wants to merge 1 commit into from

Conversation

kylecannon
Copy link

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
License MIT

After changing the bcrypt logic from Symfony to ircmaxell/password-compat in b2e553a the salt was never passed to the password_hash method.

This actually still occurs in 9d089ef as well:

if (function_exists('password_hash')) {
   return password_hash($raw, PASSWORD_BCRYPT, array('cost' => $this->cost));
}

I don't know if there wasn't salt support previously which is why it was never implemented before. Since a lot of the logic was changed in the 2.3 branch in the class BCryptPasswordEncoder i thought it would be better to issue a pull request here.

@mvrhov
Copy link

mvrhov commented Jun 6, 2013

You don't need the salt. bcrypt adds it automatically!

@fabpot
Copy link
Member

fabpot commented Jun 6, 2013

We should add a comment to make it clear that the salt is not needed.

@jakzal
Copy link
Contributor

jakzal commented Jun 6, 2013

I guess the confusion comes from the php docs. The example you can find there uses the bcrypt encryption with salt.

@stloyd
Copy link
Contributor

stloyd commented Jun 6, 2013

Isn't this PR correct? In method params we have $salt:

public function encodePassword($raw, $salt);

Yet it's not used when calling password_hash():

return password_hash($raw, PASSWORD_BCRYPT, array('cost' => $this->cost));

And according to documentation:

If omitted, a random salt will be created and the default cost will be used.

IMO it's not expected behavior, as we can pass salt, but it will be not used anyway, or I'm wrong? =)

@mvrhov
Copy link

mvrhov commented Jun 6, 2013

IMHO the bcrypt will generate a better salt than whatever algorithm most developers will come up with.

@stloyd
Copy link
Contributor

stloyd commented Jun 6, 2013

I can agree, but this behavior (adding ability to pass salt and not using it) is not correct.

@bendavies
Copy link
Contributor

here is how php would generate a salt if not supplied
http://lxr.php.net/xref/PHP_5_5/ext/standard/password.c#1111

@jakzal
Copy link
Contributor

jakzal commented Jun 6, 2013

How about using the provided salt if it's not empty and rely on php otherwise?

@mvrhov
Copy link

mvrhov commented Jun 6, 2013

Well you'll have to be pretty smart when using provided salt.

  • it has to be >= 22 characters long
  • if the passed salt is in already base64 encoded and it's the default encoding you are going to loose bits

and probably more.

@kylecannon
Copy link
Author

The way I looked at this is if you're giving someone the option to pass the salt and it's not being used then why is it even an option? I now see that it is generated if it's not passed but I assumed that when I would pass the salt it would use the salt I provided. Either I think it should be removed from the method or we should pass it so the developer has the option to use the automatically generated one or their own.

@mvrhov
Copy link

mvrhov commented Jun 6, 2013

Because the encodePassword and isPasswordValid functions are part of an interface!

@kylecannon
Copy link
Author

It's not an interface when you're using ircmaxell/password_compat because you're not running PHP 5.5

@stof
Copy link
Member

stof commented Jun 6, 2013

@kylecannon The fact that the password_compat library is used does not change the fact that the PAssswordEncocerInterface implemented by the class requires the salt in the signature.

@fabpot
Copy link
Member

fabpot commented Jun 13, 2013

I've submitted another PR (#8266) that adds the salt, but also document why it is almost never a good idea to do so.

fabpot added a commit that referenced this pull request Jun 13, 2013
This PR was merged into the 2.3 branch.

Discussion
----------

[Security] fixed usage of the salt for the bcrypt encoder (refs #8210)

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8210
| License       | MIT
| Doc PR        | n/a

see #8210

Commits
-------

b5ded81 [Security] fixed usage of the salt for the bcrypt encoder (refs #8210)
@fabpot fabpot closed this Jun 13, 2013
fabpot added a commit that referenced this pull request Jun 23, 2013
* 2.3: (33 commits)
  [Form] fixed INF usage which does not work on Solaris (closes #8246)
  Fix grammar
  Removed PHP 5.5 from the allowed failures.
  [Intl] Fixed tests failing on PHP 5.5
  bumped Symfony version to 2.2.4
  updated VERSION for 2.2.3
  update CONTRIBUTORS for 2.2.3
  updated CHANGELOG for 2.2.3
  [DependencyInjection] Replaced try/catch block with an @ExpectedException annotation in a test.
  [CssSelector] tweaked README file (closes #8287)
  added a node about HTML extension in readme
  [Console] Fixed the table rendering with multi-byte strings.
  Feature/fix unit tests
  [Process] Disable exception on stream_select timeout
  [HttpFoundation] fixed issue with session_regenerate_id (closes #7380)
  [DomCrawler] added a note about the default charset
  Throw exception if value is passed to VALUE_NONE input, long syntax
  fixed date type format pattern regex
  [Security] fixed usage of the salt for the bcrypt encoder (refs #8210)
  [FrameworkBundle] tweaked previous merge (refs #8242)
  ...

Conflicts:
	src/Symfony/Component/HttpKernel/Kernel.php
@greg0ire
Copy link
Contributor

@stof : Maybe the interface method signature should be changed to add null as default value for the salt argument, like this :
public function encodePassword($raw, $salt = null);, to avoid a client code like this : $encoder->encodePassword($user->getPlainPassword(), null) ?

@stof
Copy link
Member

stof commented Nov 21, 2014

@greg0ire this cannot be changed until 3.0. Making a param optional in an interface is a BC break, because it forces all implementations to update their signtures to make it optional as well

@greg0ire
Copy link
Contributor

You're right, I did not think of that. Should I open a new issue? I think this change is important since bcrypt is recommended in the best practices document.

ostrolucky pushed a commit to ostrolucky/symfony that referenced this pull request Mar 25, 2018
* 2.3: (33 commits)
  [Form] fixed INF usage which does not work on Solaris (closes symfony#8246)
  Fix grammar
  Removed PHP 5.5 from the allowed failures.
  [Intl] Fixed tests failing on PHP 5.5
  bumped Symfony version to 2.2.4
  updated VERSION for 2.2.3
  update CONTRIBUTORS for 2.2.3
  updated CHANGELOG for 2.2.3
  [DependencyInjection] Replaced try/catch block with an @ExpectedException annotation in a test.
  [CssSelector] tweaked README file (closes symfony#8287)
  added a node about HTML extension in readme
  [Console] Fixed the table rendering with multi-byte strings.
  Feature/fix unit tests
  [Process] Disable exception on stream_select timeout
  [HttpFoundation] fixed issue with session_regenerate_id (closes symfony#7380)
  [DomCrawler] added a note about the default charset
  Throw exception if value is passed to VALUE_NONE input, long syntax
  fixed date type format pattern regex
  [Security] fixed usage of the salt for the bcrypt encoder (refs symfony#8210)
  [FrameworkBundle] tweaked previous merge (refs symfony#8242)
  ...

Conflicts:
	src/Symfony/Component/HttpKernel/Kernel.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants