-
Notifications
You must be signed in to change notification settings - Fork 68
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
DOS when run server side #164
Comments
Just FYI, i've proved this working in your demo site. Even with just a 100 char password, causes browser to timeout while calculating for minutes. Obviously that isn't a big deal for a client side check: "don't do that and it won't freeze up dummy". But for server side applications, this is a good way for someone to lock you up. |
Thanks for the report! This makes sense 🤔 What do you mean by On the demo page he l33t string is already killing the browser with only 25 characters and takes 12 seconds for 20 chars. I personally would go with a maxSubstitutions with a default value of 100. Everything above it will not be checked with the l33t matcher. This would result in a maximum of like 5-6s |
Yes a max length index record for each dictionary, so possibly save the length of the longest string loaded into each dictionary, and only do checks against the dictionary if the part of the password we are checking is sized within what the dictionary even contains. Should short circuit a whole bunch of logic. One of the other implementations went did it this way: formigarafa/zxcvbn-rb#7 |
But yes, the performance of this implementation can be crippled by much smaller lengths of strings. If you fix some of the algorithmic problems that may be causing the slow-down it'll likely improve overall performance on some non-pathological data cases as well. I was having it run 100 characters of that string run within a second prior to any modifications of Nbvcxz:
|
Ah yes i implemented it like in the ruby code and the calcTime dropped significantly. For example But i think i keep the maximum of substitutions and increase the default value. I don't think there is any thing worth it if there are hundreds of substitutions for a password. It will be strong anyway |
I'd honestly agree with you. Maybe measure and see what threshold it starts to degrade performance vs accuracy wise and use that to decide what the limit of substitutions is, Edit: To answer my own question it looks like I have a magic value of 100 to stop at for my implementation. I forgot I did that.
I look at it as this isn't meant to be an exhaustive search, as that would have an unbounded time requirement. We have to limit the search space by making assumptions that will hold up for the general case but may let a couple insecure passwords through thinking they are secure. The HIBP stuff (I really need to sit down and implement that for Nbvcxz) and the LD calculations help alleviate the need for such an exhaustive search to get a good enough match (if one exists) even for edge cases. |
I just checked the performance with I tested it with 100 runs and calculated the avg: |
Hey, just wanted to let you know I've gotten reports from users of my library Nbvcxz that are getting a DOS every so often by specifically crafted passwords.
I even found a tool created by a government contractor used for issuing a DOS against programs using libraries containing the vulnerable (to combination explosion) algorithms from the original zxcvbn implementation:
I've solved this by implementing a maxLength type configuration...but that isn't totally done yet as I feel like I still need to have it do dictionary checks against the full-length password without any transformations. Working on finishing that feature and putting out a release.
I know this is usually used client side...however Node.js is a thing.
The text was updated successfully, but these errors were encountered: