Problem/Motivation

It is possible to work around the password requirements when registering or saving user programmatically using user_save() for example. I don't think this is a security vulnerability for sites that rely on Drupal's built-in forms to manage users, but modules that call user_save() themselves will be able to work around those restrictions. For example one could imagine a site using the services module and creating users programmatically or via some service. Users with weak passwords might be created via this flow, exposing the site to intrusion.

Proposed resolution

I looked if it's possible to intercept the raw password via some hook invoked by user_save(), but in Drupal 7, user_save() hashes the raw password right away before calling any hook.

In Drupal 6 the raw password is available in hook_user when $op is 'update', but some module like phpass neutralize it before password_strength's hook implementation is invoked, that said, adjusting password_strength's module weight to -1 allows to intercept it.

Remaining tasks

I'm not sure this can easily be achieved in Drupal 7. I think we should at least have a note on the project description page warning users that users created or updated programmatically will not have their password' strength enforced, and that it's up to the developer to check the password against the password_strength API.

Comments

scor’s picture

Title: Password strength requirement are not enforced at the user API level » Password strength requirements are not enforced at the user API level
scor’s picture

Thinking about this some more, a way forward might be to lock a user account until the password has been set via the regular form flow. For example:
- user gets created programmatically (services or custom code calling user_save). The password strength logic does not get triggered.
- user tries to login using their password: password_strength blocks user login validation because password_strength_get_user_score() return NULL (the user never set their password).
- a message warns the user that they must login using a one-time login link
- the user request a one-time login link or use drush uli
- they go through the form password widget, which will register their password strength
- next time the login will validate because password_strength_get_user_score() will return a value > 0