On Fri, Jul 26, 2024, at 08:44, Rowan Tommins [IMSoP] wrote: > > > On 25 July 2024 23:54:53 BST, Nick Lockheart <li...@ageofdream.com> wrote: > >Doesn't password_hash() handle this automatically? The result of the > >password_hash() function includes the hash and the algorithm used to > >hash it. That way password_verify() magically works with the string > >that came from password_hash(). > > For password hashing, you are always retrieving the hash for a specific user, > and then making a yes/no decision about it. Indeed, it's an explicit aim that > an attacker can't take a password and quickly scan a captured database for > matching hashes.
You’d be surprised how many projects get this wrong and claim it isn't a security issue. If you can get the hashes, you likely have the ability to run arbitrary sql commands and since password_hash stores the salt right in the hash, you just need to crack one easy to guess password -- or just run password_hash on your machine ... then copy it to whatever user you want to login as. Very few php projects salt the passwords with something application/user specific (see: symfony's legacy password implementation which does, and new one which does not; and yes I reported it, and yes, it "isn't a security issue") to prevent this from happening. There are other bad defaults, such as pdo_mysql allowing more than one sql statement (but all other drivers not -- and mysqli is also not)... making it even easier to open yourself up to getting hacked if you use pdo with mysql; allowing a single injection to be used to insert/update or even drop tables. Security is something hard to get right, for any language and framework. PHP isn't an exception here; you have to pay attention to what you are doing and think like an attacker, every step of the way. > > For other uses of hashes, though, the opposite is true: you want to search > for matching hashes. For instance, when you store a file in git, it > calculates the SHA1 hash of its content to use as a lookup key. If that key > already exists in the local database, it assumes the content is the same. > > That also demonstrates another difference: hashes are often shared between > applications, where they need to be using an agreed algorithm. If a package > manager requires SHA1 hashes of each file, you can't just substitute SHA256 > hashes without some other agreed changes. > > Tempting though a "secure_hash" function is, I don't think it's practical for > a lot of the places hashing is used. I think we can borrow from a recent RFC to return more than one thing: secure_hash($data, $algorithm = null): [$algorithm, $hash, $updated_algorithm, $updated_hash]; if you pass in an algorithm, it has to have been considered "secure" within the last two major versions*, it also returns an optional "updated" part, where it can be used to update the hash in your database, if needed. — Rob