Problem/Motivation

RegisterForm exposes the plaintext password both in the form state and on a dynamic password property on the user entity object.
Exposing plaintext passwords is a bad security practice, it could lead to contrib code handling it incorrectly, leaking it if the object is serialized, etc. We should not expose it on the entity and we should remove it from the form state as soon as we don't need it anymore (after the form submit handler has been called).

In \Drupal\user\RegisterForm line 115 has:

    // Add plain text password into user account to generate mail tokens.
    $account->password = $pass;

Drupal 8 doesn't support such a token, and it looks like this in NOT the hashed value set by \Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem because we copy it before calling $account->save();

The same lines exist in Drupal 7 and is also a possible (minor) security weakness since the plain text password may be passed through the mail system even though Drupal 7 no longer supports a plain-text password token (Drupal 6 still does).

In Drupal 7 see line line 3925 in user.module:

  // Add plain text password into user account to generate mail tokens.
  $account->password = $pass;

Proposed resolution

Deprecate accessing this property.

An in a future release remove the code that sets $account->password.

Remaining tasks

User interface changes

none

API changes

none

Data model changes

none

CommentFileSizeAuthor
#2 2648272-2.patch1.55 KBpwolanin

Issue fork drupal-2648272

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

pwolanin created an issue. See original summary.

pwolanin’s picture

Issue summary: View changes
Status: Active » Needs review
Issue tags: +Security improvements
StatusFileSize
new1.55 KB

Quick 1st pass patch

mgifford’s picture

Removing code seems fine since it seems not to be supported in D8 any more. I can see how unsetting the pass value could help, but that should be described in the issue more.

+    // Remove the plain text password from the form state.
+    $form_state->unsetValue('pass');

Manual testing for the generated mail tokens is probably a good idea too.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dpi’s picture

Title: Remove outdated code that sets password on $account during user registration » Add a password token for new user registrations
Category: Bug report » Feature request
Status: Needs review » Active
Issue tags: +user password, +tokens

Drupal 6 had the !password token for passwords. There is no official [user:password] token for Drupal 7 or 8. Unfortunately I cant find an issue outlining rationale for removing the password token in D7.

Perhaps this issue should be about adding a password token, and changing the $account->password code to be something that isnt creating dynamic properties.

If it is decided that we dont need a password token, then remove the above code.

For reference, the Registration Password Token project is dedicated to adding this token to Drupal 7 and 8. Both versions rely on this dynamic $user->password value to be set.

dpi’s picture

Title: Add a password token for new user registrations » Add a password token

Actually this token would need to be made available on user save events to accommodate potential password modifications on the edit form. So this doesnt just affect user registrations

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kingandy’s picture

@dpi, I believe the primary reason for removing the password token is that it is bad security practice to display or transmit a user's password in any form. We can argue about what methods of data transfer are and are not safe, but at the end of the day the only 100% guaranteed secure decision is to simply not expose it, and that's the decision the Drupal team have made.

On a technical level (AIUI) it is no longer possible to extract a user's password for display, as the login system has been moved over to a one-way encryption algorithm - the system itself can't decrypt a stored password. (There's really no need to, even at login - instead it encrypts the entered password using the same algorithm and compares it with the stored one.) So that is a pretty big barrier to making such a token generally available even if you wanted to, which, as noted, is a super bad idea.

The RPT module does a very specific job of making the token available in registration emails, which it's only able to do because the password has not yet been encrypted at that point (the form submission is still available). Adding a password token to the system does not look like an practical or desirable option at this time.

kingandy’s picture

Title: Add a password token » Remove outdated code that sets password on $account during user registration
Category: Feature request » Bug report
Status: Active » Needs review

Restoring the former task title and category/status.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

If this is a bug it will need a test.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mr.baileys’s picture

We should be careful when removing this, since some contrib modules seem to rely on this property being set (so a bit of an undocumented API?). See for example https://www.drupal.org/project/logintoboggan/issues/1165126.

dcam’s picture

Category: Bug report » Task
Issue tags: -user password, -tokens, -Needs tests

It doesn't make sense to me that this issue was filed as a bug report. A quick search for other "dead code" issues in the Core queue shows that they're mostly/all Tasks.

I considered the suggested test:

Possibly add test for D8 to insure that the password is the hashed value after save() if no such test exists.

I even wrote one out, but in the end this is no different from a Functional test where the login form is submitted. That's covered by UserRegistrationTest. If I'm wrong, then tell me. Needing a test for this doesn't make sense to me. The other dead code issues I checked don't require a test for it either. So I'm removing the Needs Tests tag (along with other superfluous tags).

Aside from that, I also wondered why PHPStan didn't pick up on this. This line contains an undeclared class property assignment. I figured that should be setting off a standards error. But it doesn't because Core only lints with PHPStan level 1. Those warnings are activated at level 2. You can cause an error to occur manually with the command vendor/bin/phpstan analyze --configuration=./core/phpstan.neon.dist -l 2 core/modules/user/src/RegisterForm.php.

smustgrave’s picture

Still seems to be solving a problem vs just removing code so probably would still vote for a test to show whats needed

#22 should be considered too

dcam’s picture

Would you prefer to deprecate it instead of removing it immediately?

prudloff made their first commit to this issue’s fork.

prudloff’s picture

Status: Needs work » Needs review

I added a test.

smustgrave’s picture

Status: Needs review » Needs work

think this should have an issue summary about why it's needed, not super clear. Also how are we covering instances in contrib that could be relying on this? See #22

prudloff’s picture

Issue summary: View changes
Status: Needs work » Needs review

I added an explanation at the beginning of the summary.

how are we covering instances in contrib that could be relying on this?

This is an undocumented property. Is it OK to remove it in a major release or do we need to deprecate it first?

smustgrave’s picture

Would assume it would need some kind of deprecation.

smustgrave’s picture

Status: Needs review » Needs work

Wonder if something similar can be done like in EntityBase for original

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

prudloff changed the visibility of the branch main to hidden.

prudloff’s picture

Issue summary: View changes
Status: Needs work » Needs review

I opened a new MR that deprecates the property instead of removing it.

smustgrave’s picture

Title: Remove outdated code that sets password on $account during user registration » Deprecate retrieving password from $account
Status: Needs review » Reviewed & tested by the community

Updated title to match what's going on. Am wondering if this one should be removed in 13 but will let committers decide. Seems like a good deprecation.

longwave’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed
Issue tags: +Needs followup

Thanks for the discussion above. While contrib modules do seem to be using this, given this is a security improvement I think we should just get rid of it sooner rather than later - so let's deprecate in 11.4 for removal in 12. It is obvious we should not be storing plaintext passwords at all and modules that were relying on this feature will have to find another technique if they really need it.

Crediting everyone on this issue for the discussion. Tagging for a followup to remove the deprecation and the setter from main/12.0.

Committed and pushed 9e6f0a2cd9f to main and ba93099d48a to 11.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • longwave committed ba93099d on 11.x
    task: #2648272 Deprecate retrieving password from $account
    
    By: pwolanin...

  • longwave committed 9e6f0a2c on main
    task: #2648272 Deprecate retrieving password from $account
    
    By: pwolanin...
longwave’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.