Problem/Motivation

The PasswordConstraint password_policy_character_constraint requires unique characters of each type. That is, if for example the module is configured to require passwords to include two numbers, a password which includes two incidences of the same number will fail validation. This runs counter to common user experience and actually decreases password security; if a malevolent user knows that a password contains any one character, they know that that character is not repeated anywhere in the password, making the password easier to crack.

Steps to reproduce

Enable this module, set a constraint requiring that passwords include two numbers, log in as a user to which this constraint applies and try to set the a new password that includes two of the same numbers. (This problem is not limited to numbers; the same is true for letters, upper case letters, lower case letters and special characters.)

Proposed resolution

Alter the logic in PasswordCharacter::validate() to add the number of incidences of each character instead of increasing counters by one.
For example, change:

  if (is_numeric($char)) {
    $count_numeric++;
  }

to:

  if (is_numeric($char)) {
    $count_numeric = $count_numeric + $val;  // Here, $val is the the number of incidences of the $char in the password.
  }

Remaining tasks

Community discussion is appropriate as to whether we should adapt the module's admin language (see related issue Instructions unclear for constraint of Uppercase and Lowercase Characters) to align with the module's requirement that characters used be unique or should we remove that requirement.

Patch forthcoming.

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

COBadger created an issue. See original summary.

cobadger’s picture

Assigned: cobadger » Unassigned
Status: Active » Needs review
StatusFileSize
new1.32 KB

Patch attached.

Status: Needs review » Needs work
cobadger’s picture

Status: Needs work » Needs review
StatusFileSize
new1.78 KB

Updated patch with correction to unit test.

Status: Needs review » Needs work
hmendes’s picture

Hello,
When a first used this functionality I was also confused about this, when I read the description I thought this constraint was to count the amount of characters in the password for each type ( not about unique characters ), and that's why we had the issue #2894929: Instructions unclear for constraint of Uppercase and Lowercase Characters to change these descriptions to make it clearer.

Although I think this could be done, I also think that the initial functionality ( with unique characters ) might be a good idea... I think we could we add an option, a checkbox, to choose between counting unique characters or count every character, what do you think?

cobadger’s picture

Status: Needs work » Needs review
StatusFileSize
new2.02 KB
new286.99 KB

(Updated patch with corrected unit testing attached.)

@hmendes thank you for your thoughts on whether or not we want to provide a unique character password constraint. I believe that requiring unique characters decreases password security: Of the top 10,000 most commonly used passwords, only about 36% contain only unique characters (see attached "most-common-10000-passwords-unique-characters.ods"), so enforcing a unique character constraint would make it about 64% easier for common password attacks to work - a significant decrease in password security.

Status: Needs review » Needs work
cobadger’s picture

Status: Needs work » Needs review
cobadger’s picture

StatusFileSize
new2.02 KB

I sincerely apologize for bombing this ticket with updated versions of the patch. The attached patch's tests should all pass this time.

marcos_lima’s picture

Assigned: Unassigned » marcos_lima
Status: Needs review » Needs work

Hi @COBadger! Thanks for the patch! I tested it and did a code review. I installed the module, tested the password change before and reproduced the issue, then tested again after applying the patch and the expected behavior (counting two or more incidences of the same character) was working fine. The code logic and modifications seem good to me! I would just like to get some more info on the test changes, because I think it is redundant with the previous data. If you meant for it to test the new behavior, I think the data should be:

[
  4,
  'letter',
  'pass',
  TRUE,
],

To assert if it is really counting the two “s” as two letters. The way it is, with ‘passw’, it would pass in the previous behavior and in the proposed one, thus becoming redundant.

As seen by the last provided data in the test, I think it was expected during its implementation that this functionality enforced unique characters in its constraints.
I agree with @COBadger thought that it is counterintuitive and runs against common user experience. From what I understood reading the IS and the discussion, this constraint should either:

  1. Remove the unique characters requirement and allow equals characters, counting the sum of them like in the patch @COBadger made and the IS proposed resolution; or
  2. Be worded correctly in the description and explicitly show that it enforces unique characters in the constraint, and maybe allow the user to set another constraint that allows for equal characters, like what @hmendes said.

Right?
I prefer the first approach, which is the one proposed, and agree with @COBadger arguments. Then we could add the unique characters constraint as a feature request if the community thinks it is needed.
I’m moving it back to Needs Work and assigning myself to make that test change. Apologies if I misunderstood something and thank you for the patch. I hope my thoughts were useful for the discussion.

marcos_lima’s picture

Assigned: marcos_lima » Unassigned
Status: Needs work » Needs review
StatusFileSize
new2.02 KB
new493 bytes

Hi! Attached is the patch with the change in the test data and the interdiff from the previous patch.

huriellopes’s picture

Status: Needs review » Reviewed & tested by the community

Steps performed:
(1) Module installed
(2) Reproduction of the problem.
(3) Patch applied.
(4) Code review on changes.
(5) Retested with patch, issue resolved.

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

kristen pol’s picture

Assigned: Unassigned » kristen pol

Assigning to myself as I'm reviewing/merging ready RTBC fixes/updates over the next few days.

kristen pol’s picture

Version: 8.x-3.x-dev » 4.0.0

This should be against 4.0.x as 8.x branches are no longer supported, so changing version.

kristen pol’s picture

Assigned: kristen pol » Unassigned
Status: Reviewed & tested by the community » Needs work

Thanks everyone for the work on this issue. Moving back to needs work based on the following:

I've tested the original behavior and read the summary and comments above.

1. Regarding repeating characters, I found this:

Repeating characters is a different story. The current NIST standards explicitly say that complexity rules should not be used. (Examples of complexity rules include requiring upper AND lower case, special characters or numbers, denying passwords with repeating characters, etc.) So current NIST guidelines recommend against restrictions on repeating characters.

https://www.quora.com/How-does-restricting-password-length-or-repeating-...

I ready some other posts that talk about this as well. So, rather than add a "unique" checkbox per #6, I think we can move forward with this approach.

But this claims to be a list of NIST guidelines:

https://blog.netwrix.com/2022/11/14/nist-password-guidelines

which has:

Users should be prevented from using sequential characters (e.g., “1234”) or repeated characters (e.g., “aaaa”).

There is already a consecutive character constraint that can be used though I don't see a sequential one. A separate feature request issue can be created to add sequential character constraint.

2. The MR does not match the most recent patch. I'm okay with an MR or patch, so whoever updates can do either.

3. Nitpick: The logic could be slightly simpler, e.g.

$count_numeric = $count_numeric + $val;

could be:

$count_numeric += $val;

4. The documentation/messages should be updated to reflect these changes:

#2894929: Instructions unclear for constraint of Uppercase and Lowercase Characters

cobadger’s picture

Status: Needs work » Needs review

Not sure why it's not automatically being added to this page, but I created a new MR against 4.0.x:

https://git.drupalcode.org/project/password_policy/-/merge_requests/72

kristen pol’s picture

Assigned: Unassigned » kristen pol

Assigning to myself for review.

kristen pol’s picture

Assigned: kristen pol » Unassigned
Status: Needs review » Fixed

Thanks everyone. I reviewed the code and tested MR 72 and it works as expected. This has been merged and will be in the next release.

That said, there still might be missing tests. Don't we want to test things like the following? If so, we can have a followup issue with more tests.

1. We set min numbers to 3 and we set password to 3 numbers that are the same.

2. We set min numbers to 3 and we set password to 3 numbers that are the different.

3. We set min numbers to 3 and we set password to 2 numbers that are the same (or different).

4. We set min numbers to 3 and we set password to 4 numbers that are the same (or different).

Status: Fixed » Closed (fixed)

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

kristen pol’s picture

Version: 4.0.0 » 4.0.x-dev

This is part of the new 4.0.1 release.