For example with blowfish it returns something like:
That contains info about the type of hashing alg and it contains the salt. A lot of resources say to just store this value in the db and it will be secure. But couldn’t someone just test a common list of passwords against these values to crack some of them?
The security of password hashing does not come from information being secret. You have already discarded the actual secret, namely the password that is the basis for the hash value. The remaining hash is simply a sort of fingerprint of this original data. The security comes from the fact that it is not possible to derive the original data from the hash. The only possibility is to try all possible passwords and see which produces the same hash. The security here comes from the fact that this is computationally very expensive and unlikely to succeed in a useful amount of time.
The salt is only introduced to prevent somebody from using an already precomputed set of known hashed passwords, forcing an attacker to actually rehash all possible passwords with the unique salt. The salt itself is not secret, neither is the hashing algorithm.
In short: yes, that value is absolutely safe to store in a database.
The hash generated by
crypt() is specifically intended to be stored. No matter what your password hashing scheme is, if somebody gets hold of your database contents, they will be able to brute-force your passwords, and you don’t have the option of not storing password hashes at all. The algorithms applied by
crypt() are specifically selected because they take significant time to calculate the hash; this is not apparent when you only test one password, but brute-forcing thousands of passwords becomes impractically slow.
But couldn’t someone just test a common list of passwords against
these values to crack some of them?
You could always do no matter how the passwords are stored. The crypt function does not prevent this, but it will make it really really slow. If a user uses a really common password (as 123456) no hashing algorithm in the world will protect him.
If you disallow those simple passwords and use a good hashing algorithm (that crypt() supply) you have done your best to protect the passwords.
If someone has access to your database then they would have access to the salt either way, since you should be using a different salt for every users password (which you most likely would store along in the database).
The point of the salt is so that rainbow tables don’t work. The individual would have to re-hash every combination of password + salt in order to determine the password. You use a different salt on each password so he has to re-generate millions of hashes for each one.
Some more good information on crypt can be found here:
Why does PHP crypt() prepend the salt to the hash?