> Why? Because my password in the "create" page was silently truncated on the front end, but the same truncation does not occur in all places, so I would type a longer password on the login page then what was registered in the system and it would fail.
Here's an even worse one than truncating the end of long passwords: truncating internal whitespace
The change/reset password dialog for Apple ID does this. If your password is "foo bar baz bam" then it will happily convert it to "foobarbazbam" but not tell you it did so. Then when you go to log into your Apple ID on your phone, you include the whitespace, you try repeatedly and then lock your account (temporarily). Then you do it again...
Some general advice is:
- Don't silently truncate anything (i.e. don't limit the length)
- Don't silently transmute anything (i.e. don't convert to lowercase)
- Don't have a password max length with a limit less than $BIG_NUM chars[1]
- Do give the user feedback rather than silently doing anything.
[1]: You're hashing them anyway right? So the storage doesn't change. Though if you're using something like bcrypt be aware of the max hashed length: https://security.stackexchange.com/questions/39849/does-bcry.... Also you can work around that by hashing the entire uses password (with say SHA-512) prior to inputting into bcrypt.
> Also you can work around that by hashing the entire uses password (with say SHA-512) prior to inputting into bcrypt.
I wonder why people are so eager to combine different hash algorithms, especially a strong with a weaker one. If this is isn't a well-established anti-pattern, it should become one.[1] Why? Because in some sense it combines the weaknesses of both algorithms.
Assume your password hash is:
h(p) = bcrypt(sha512(p))
Assume in the future somebody generates a sha512() collision with p and q, while bcrypt() holds water:
sha512(p) = sha512(q)
It follows that:
bcrypt(sha512(p)) = bcrypt(sha512(q))
and hence:
h(p) = h(q)
So any collision in sha512() translates directly to h(), bcrypt's strength is unable to protect you from that.
Had you just used bcrypt(), you would not have been affected.
Frankly, this is about collision and not about preimage attacks (the latter being more relevant for password cracking), but the former is usually a first step towards the latter. Also, this example demonstrates that combining a weaker and a stronger hash algorithms usually does not combine their strengths, but their weaknesses.
[1] It is almost like inventing your own crypto primitives, which actually is a well-established anti-pattern.
While the collisions themselves would increase it's not statistically significant to cause an issue in practice. Plus the idea here isn't to increase the strength of the overall construct. It's to ensure that all characters that the user entered have some contribution to the final product.
What I'd consider a much worse issue is considering the following to be the same by silently truncating things:
- some really long password ... that ends with foo
- some really long password ... that ends with bar
- some really long password ... that ends with baz
The only acceptable alternatives when using something like bcrypt are:
- Restrict user passwords to 72 bytes (not chars!)
- Hash with something like SHA-512 prior to passing them to bcrypt.
People are eager to combine different hash algorithms frequently because they desire to hedge against weaknesses in one of the algorithms. Or, in this case, because they want to shore up an existing 'weakness' in one of the algorithms (for bcrypt, its maximum input size).
You are correct that doing this ad-hoc should be an 'anti-pattern'. There are subtle details (see the papers linked above...). However, the idea itself is sound, if handled properly.
One thing to note is that if you manage to get access to just the hashes, they won't have sha512(p), so they wouldn't be able to figure out sha512(q). So while your are correct that there is (technically) a weakness there, it's not one that's actually exploitable.
Can you explain how a collision helps? I mean, there's trivial collisions with the truncation that would be used instead. That doesn't mean that bcrypt(f(x)) is any weaker because there may be some other x' that f(x) = f(x').
I'm siding with vog here. Do not compose hashes¹. You may not think it's relevant that it degrades the security of your site, but nobody knows what consequences it will bring, so how could you know?
Impose your size limitation as a clear password rule. That means, write on your site that passwords must not exceed the 55, 255 or whatever characters, send back an error if the user tries to create a larger password.
1 - And completely avoid weaker hashes in general, it's not like a percent or two increase in CPU usage will have a greater impact on your bottom than having to adapt your software after it's out.
I can confirm. I spent days locked out of my Apple account (and all associated devices) because I had spaces in my passwords. After several hours with support, who needed to escalate the issue to tier 2, then engineering, the only thing that fixed it was me briefly trying a simple password -- one without spaces. I'm not sure if the issue was ever fixed, but I don't imagine I'll use spaces in an Apple password again anytime soon.
Wonder what other sins are there. A couple of years ago when iCloud was first a thing, I did a couple of password changes in quick succession. It resulted in me having different login passwords for different iCloud services. It worked for a short time then broke and another reset fixed it all.
Enforced password reset questions. There's a limited set of about 10 questions (trivial stuff like "where were you born?"), and you have to set 3 of them. About half a year ago, I was forced to do this in order to be able to log in again (I'm only occasionally using it for publishing iOS apps). What is this, Hotmail in 2005?
And the questions haven't changed in decades. It's pretty simple to figure out things like "name of high school attended", "street you grew up on", "model of first car", "mother's maiden name", etc for just about anyone who has a social media account.
As my dad pointed out, the answers are passwords. If you restricted passwords to every possible make of car, for example, it would be incredibly weak - too little total entropy in the possible answers.
(Love the name of the high school mascot, by the way!)
> As my dad pointed out, the answers are passwords. If you restricted passwords to every possible make of car, for example, it would be incredibly weak - too little total entropy in the possible answers.
United Airlines does exactly this and it's hilariously insecure. The secret questions are preselected and the answers must be from their set of answers for each. There's only 8-10 choices for each (ex: Favorite music? pop / jazz / classical / etc).
> (Love the name of the high school mascot, by the way!)
There 10 types of people. Those that got that joke and ...
My favorite restaurant in college is a high-end hotel in Johannesburg (actually it's not, and I've never even been to Africa unless you count a week I spent on Tenerife as a child).
> You're hashing them anyway right? So the storage doesn't change
No, but the time spent computing the hash does change and you open yourself to denial of service attacks. Just pick a max password length of like 200, or whatever your hashing algorithm mandates (55 for bcrypt).
Extremely large password sizes can lead to a DDOS attack on the server (due to computation complexity curve). A large size such as 4096 characters is perfect. Don't accept a password that is 10GBs in size. But don't limit to MAX 16 characters either.
Oh yeah! Freedompop actually transformed a space into a "+" (or vice versa). And this is just free internet I set up for my dad. Took us like an hour to figure that one out.
I'm guessing whatever they used as an HTTP client did it for them. It's a fairly common way to encode spaces (the alternative being %20 of course - encoding as "+" looks much cleaner).
Here's an even worse one than truncating the end of long passwords: truncating internal whitespace
The change/reset password dialog for Apple ID does this. If your password is "foo bar baz bam" then it will happily convert it to "foobarbazbam" but not tell you it did so. Then when you go to log into your Apple ID on your phone, you include the whitespace, you try repeatedly and then lock your account (temporarily). Then you do it again...
Some general advice is:
- Don't silently truncate anything (i.e. don't limit the length)
- Don't silently remove anything (i.e. don't remove whitespace)
- Don't silently transmute anything (i.e. don't convert to lowercase)
- Don't have a password max length with a limit less than $BIG_NUM chars[1]
- Do give the user feedback rather than silently doing anything.
[1]: You're hashing them anyway right? So the storage doesn't change. Though if you're using something like bcrypt be aware of the max hashed length: https://security.stackexchange.com/questions/39849/does-bcry.... Also you can work around that by hashing the entire uses password (with say SHA-512) prior to inputting into bcrypt.