According to http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html nginx can read password hashes of these types:
crypt(), apr1, SHA1 & SSHA.
This is how I understand how these hashes work and what the problem with them is:
crypt() discards everything after the 8th character, so if my password is 12345678UltraSecurePa$$w0rd
I can successfully login with typing 12345678
. Doesn't that defeat the purpose of a strong (lengthy) password? Brute forcing through 8 any character password seems to be trivial these days. I don't understand why crypt should be more secure than plaintext.
apr1 is MD5 but slowed down a thousand times. Which is still very weak these days. One can find reports of brute forcing through > 300.000.000.000 (300 billion) hashes per second with a couple of GPUs.
SHA1 is not very much better than MD5. It is a hashing algorithm optimized to be fast and thus is vulnerable to brute force attacks. Also, it is not salted in this case.
And the last method is salted SHA1. This seems to be the least weak method for hashing http basic auth passwords in nginx. But when someone steals the hash, he also has the salt (the salt is just base64 encoded), so SSHA still has the weakness of using fast hashing algorithms for "encrypting" passwords.
nginx can't use bcrypt, or PBKDF2.
To conclude: If I want that my HTTP basic auth hashes are "secure" (secure means that it is too time expensive to crack the hashes) I have to follow these rules:
- never use crypt.
- enforce passwords with at least 16 characters because this seems to be long enough against brute force attacks (let's just ignore dictionary attacks here for a moment).
And: convince the nginx guys that they should implement better hashing methods for HTTP basic auth.
Is there an error in my conclusion?