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

T6353: Add password strength check and basic validation #4338

Draft
wants to merge 5 commits into
base: current
Choose a base branch
from

Conversation

oniko94
Copy link

@oniko94 oniko94 commented Feb 7, 2025

Change summary

  • Add functionality to check the non-default user password strength based on its entropy
  • Refactor prompting for the non-default password to check for minimal length (4 characters) and display the weak password warnings

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes)
  • Migration from an old Vyatta component to vyos-1x, please link to related PR inside obsoleted component
  • Other (please describe):

Related Task(s)

Related PR(s)

How to test / Smoketest result

  • Built a .deb package using the official Docker image vyos/vyos-build:current
  • Built an ISO image
  • Boot up a virtual machine (qemu-system-x86_64, host: Linux Mint) from the live ISO image built in the previous step
  • Run install image
  • Check:
    • Password shorter than 4 characters
    • Password with only lowercase letters'
    • Password with uppercase, lowercase letters and digits
    • Made sure in all cases the actual output matched the expected output

Checklist:

  • I have read the CONTRIBUTING document
  • I have linked this PR to one or more Phabricator Task(s)
  • I have run the components SMOKETESTS if applicable
  • My commit headlines contain a valid Task id
  • My change requires a change to the documentation
  • I have updated the documentation accordingly

Copy link

github-actions bot commented Feb 7, 2025


PR title does not match the required format

@oniko94 oniko94 changed the title vyos.utils: image-tools: T6353: Add password strength check and basic validation T6353: Add password strength check and basic validation Feb 7, 2025
@sever-sever
Copy link
Member

Copy link
Member

@dmbaturin dmbaturin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a widely used tool for password strength checking — cracklib. Debian has Python bindings in the repos (python3-cracklib) and it includes a dictionary check in addition to entropy checks. The FascistCheck function from https://github.com/cracklib/cracklib/blob/main/src/python/cracklib.py may suffice (however distasteful its name is...).

The entropy function may still be useful because we may want to set a higher cutoff point than cracklib, but we certainly should also use something for a dictionary check to prevent passwords like 'Password999?' that technically have decent entropy but can be easily cracked with a dictionary attack.

The requirement for special characters have long been proven to be counterproductive and should be removed in any case. If cracklib likes a password but it's below our entropy threshold, we can tell the user to make it longer. Otherwise we can just use cracklib's error, since it gives it in the exception message:

>>> cracklib.FascistCheck('swordfish')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: it is based on a dictionary word

# - 1 special character
# - be at least 8 characters long
PASSWORD_POLICY = {
"have uppercase characters": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requirement to have special characters and digits is still widespread but security studies found that it's misguided because it can only improve password entropy by making it less memorable. Stringing multiple words together can create passwords with very high entropy that are still easy to remember.

See the NIST recommendation and the XKCD#936 for an illustration.

If we are to go with a custom implementation, I'd remove all requirements except length, since they will prevent high-entropy memorable passwords like the-magic-words-are-sqeamish-ossifrage (entropy in the set of keyboard-typeable characters about 250).

Copy link
Author

@oniko94 oniko94 Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmbaturin Thank you for your feedback! I've taken my time to read the docs for cracklib2 and decided that indeed it would be better to use it in our case. However, this means I would need to have several system packages present apart from the Python bindings - namely, the libcrack2, cracklib-runtime and wordlist. I have made the according changes in the vyos-build repo, a pull request incoming as soon as I finish testing locally.

Until my upcoming PR to vyos-build is reviewed and approved, I think it's better not to push any changes here so that I won't clutter your CI/CD pipeline with builds that are to fail in any case (since they lack required libraries).

P.S. I have also encountered a build issue while building the Docker container locally, which required a tiny patch in the Dockerfile as well. More details in the upcoming PR.

Best regards,
Sasha

result["strength"] = "Very Weak"
case e if e in range(36, 59):
result["strength"] = "Weak"
case e if e in range(36, 119):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lower boundary is incorrect: should be 59 (mis-pasted from the previous condition?)

@@ -83,6 +86,7 @@
MSG_WARN_ROOT_SIZE_TOOSMALL: str = 'The size is too small. Try again'
MSG_WARN_IMAGE_NAME_WRONG: str = 'The suggested name is unsupported!\n'\
'It must be between 1 and 64 characters long and contains only the next characters: .+-_ a-z A-Z 0-9'
MSG_WARN_PASSWORD_TOO_SHORT: str = 'The password should be at least 4 characters long. Try again.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the message say '4' when the requirement is 8?

confirm: str = ask_input(MSG_INPUT_PASSWORD_CONFIRM, no_echo=True,
non_empty=True)

passwd_weak = check_result['strength'] not in ['Strong', 'Very Strong']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using magic strings is a recipe for fragile code. Someone decides to change it to very strong (different case) and the check will break. The usual practice is to use constants, although here there's no need for constants for different strengths, either: just for the strength cutoff (if (strength < MIN_PASSWORD_ENTROPY) or similar).

Copy link

CI integration ❌ failed!

Details

CI logs

  • CLI Smoketests (no interfaces) ❌ failed
  • CLI Smoketests (interfaces only) ❌ failed
  • Config tests ❌ failed
  • RAID1 tests ❌ failed
  • TPM tests ❌ failed

@oniko94
Copy link
Author

oniko94 commented Feb 11, 2025

vyos/vyos-build#903 @dmbaturin @sever-sever kindly review this PR - the changes added there block this one. Thanks in advance!

@oniko94 oniko94 marked this pull request as draft February 11, 2025 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

3 participants