Thread: MD5 salt in pg_authid password hashes
From the manual: | Because MD5-encrypted passwords use the role name as cryptographic | salt, renaming a role clears its password if the password is | MD5-encrypted. In backend/commands/user.c if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role), encrypted_password)) elog(ERROR, "password encryption failed"); new_record[Anum_pg_authid_rolpassword - 1] = CStringGetTextDatum(encrypted_password); I don't understand this. Why was the role name chosen as a salt? Apart from the problem that the hash becomes unusable when a role is renamed, roles names are very poor salts. Given how relatively predictable they are, the hash could just as well be left unsalted. There is a comment in libpq/md5.c which more or less acknowleges this: "Place salt at the end because it may be known by users trying to crack the MD5 output." Ignoring for the moment that cracking PG passwords is probably not very common, the position of the salt does little to prevent attacks. A random salt would eliminate both weaknesses. The only explanation I can come up with is that the current method of hashing has been kept for historic reasons, as changing to a random salt would break existing hashes. Or is there something else I've overlooked? regards, stefan PS: Strictly speaking, the expression "MD5-encrypted" in the manual is incorrect - MD5 is a hashing algorithm, not an encryption algorithm. </nitpick> -- LOAD"Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!",8,1 RUN!
On Wednesday, February 15, 2012 6:34:21 pm Stefan Weiss wrote: > From the manual: > | Because MD5-encrypted passwords use the role name as cryptographic > | salt, renaming a role clears its password if the password is > | MD5-encrypted. > > In backend/commands/user.c > > if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role), > encrypted_password)) > elog(ERROR, "password encryption failed"); > new_record[Anum_pg_authid_rolpassword - 1] = > CStringGetTextDatum(encrypted_password); > > I don't understand this. Why was the role name chosen as a salt? Apart > from the problem that the hash becomes unusable when a role is renamed, > roles names are very poor salts. Given how relatively predictable they > are, the hash could just as well be left unsalted. When you alter the role name you are told the password has been cleared. It would be fairly easy to wrap the rename and the setting of the password in a transaction. > > There is a comment in libpq/md5.c which more or less acknowleges this: > "Place salt at the end because it may be known by users trying to crack > the MD5 output." Ignoring for the moment that cracking PG passwords is > probably not very common, the position of the salt does little to > prevent attacks. > > A random salt would eliminate both weaknesses. The only explanation I > can come up with is that the current method of hashing has been kept for > historic reasons, as changing to a random salt would break existing hashes. > > Or is there something else I've overlooked? Yes: http://www.postgresql.org/docs/9.0/static/encryption-options.html " Encrypting Passwords Across A Network The MD5 authentication method double-encrypts the password on the client before sending it to the server. It first MD5-encrypts it based on the user name, and then encrypts it based on a random salt sent by the server when the database connection was made. It is this double-encrypted value that is sent over the network to the server. Double-encryption not only prevents the password from being discovered, it also prevents another connection from using the same encrypted password to connect to the database server at a later time. Encrypting Data Across A Network SSL connections encrypt all data sent across the network: the password, the queries, and the data returned. The pg_hba.conf file allows administrators to specify which hosts can use non-encrypted connections (host) and which require SSL-encrypted connections (hostssl). Also, clients can specify that they connect to servers only via SSL. Stunnel or SSH can also be used to encrypt transmissions. " > > > regards, > stefan > > > PS: Strictly speaking, the expression "MD5-encrypted" in the manual is > incorrect - MD5 is a hashing algorithm, not an encryption algorithm. > </nitpick> -- Adrian Klaver adrian.klaver@gmail.com
On 2012-02-16 04:18, Adrian Klaver wrote: > When you alter the role name you are told the password has been cleared. It > would be fairly easy to wrap the rename and the setting of the password in a > transaction. But this shouldn't be necessary. I don't get why the salt has to be linked with the role name. This problem would be a non-issue with a random salt. > Encrypting Passwords Across A Network > The MD5 authentication method double-encrypts the password on the client before > sending it to the server. It first MD5-encrypts it based on the user name, and > then encrypts it based on a random salt sent by the server when the database > connection was made. It is this double-encrypted value that is sent over the > network to the server. Double-encryption not only prevents the password from > being discovered, it also prevents another connection from using the same > encrypted password to connect to the database server at a later time. I must be missing something here... the *client* applies the salt, because he knows it, and then sends the salted hash? Then what's the point of using a salt at all? The second "encryption" layer just protects the communication channel, and has nothing to do with what I'm concerned with. It's redundant if a secure channel already exists (SSL or TLS or whatever). But I have to admit that I didn't read the source for this part, so I may indeed be missing something. > Encrypting Data Across A Network > SSL connections encrypt all data sent across the network: the password, the > queries, and the data returned. The pg_hba.conf file allows administrators to > specify which hosts can use non-encrypted connections (host) and which require > SSL-encrypted connections (hostssl). Also, clients can specify that they connect > to servers only via SSL. Stunnel or SSH can also be used to encrypt > transmissions. Just so. But this still leaves the question why the hashing/salting in PG works differently than just about anywhere else. The client isn't supposed to know or care about the salt. Normally, salting is a purely server-side protection against attackers who would generate lookup tables for common password hashes, in the hope of getting their hands on a list of actual password hashes. If the salt is as predictable as a user/role name, it's nowhere near good enough to protect against such an attack. At best, it might increase the size of the lookup tables by 2 or 3 orders of magnitude, which is no challenge at all with a good word list ("backup", "dba", "slony", "postgres", "master", ...). Compare this to a 4-byte random salt. regards, stefan -- LOAD"Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!",8,1 RUN!