The problem in two code samples
For those developers who
understand they can’t simply store the password in plain text, they
typically employ one of two mechanisms. Both are insecure.
The
first mechanism is using some type of insecure hashing algorithm, like
MD5 or SHA1. These “fingerprint hashes” produce the same hash for a
given string of characters, making them ideal for identifying files and
other items, but are not cryptographically strong enough for hashing
passwords. Even if you add a salt, your passwords will be inherently
insecure
especially since these algorithms require that the salt be stored alongside the password
for two reasons: first, you are likely to screw up the randomness of
the salt (weakening the encryption). Second, MD5 and SHA1 are meant to
be fast hash algorithms, meaning that a determined attacker can brute
force their way through your passwords with ease.
1
2
3
|
<?php
$hashed = insecure_hashing_function($salt . $password); # This is BAD
|
Another
potential failure of security for developers is somehow encrypting
passwords with a key, so they can be decrypted for various purposes. I
came across the following code sample in a project I was auditing:
The ONLY surefire way to hash passwords in PHP
So,
if “traditional” methods aren’t enough, what can a developer who cares
about security do? The answer lies in a feature introduced as of PHP
5.5: a native password hashing API for PHP.
This library contains
two functions that will make it easier for you to hash passwords:
password_hash() and password_verify(). These functions essentially wrap
built-in PHP behaviors for cryptography, but build in sane defaults that
will serve even the most inexperienced developer well.
|
<?php
$password = 'SuperS3cr3+P@ssw0rd';
$hash = password_hash($password, PASSWORD_DEFAULT);
# $2y$10$PwbhVaqzuUSl5wSdi.iCK.RBz5pQp/a.6lRdSRttY8s2qs7dn5hTq
$verified = password_verify($password, $hash);
# true
|
Astute
developers who run the above code will recognize that the hash I give
isn’t repeated by their own password_hash function. That’s by design:
each password hash should be unique, even for the same password between
different users! Also, the second argument lets developers pick the
encryption algorithm they want to use; PHP 5.5 defaults to bcrypt, which
is usually sufficient.
But I don’t have access to PHP 5.5!
Ah, that is a problem, isn’t it? PHP 5.5′s adoption rate is fairly low right now. But you’re in luck:
Anthony Ferrara has backported the native password library for earlier versions of PHP. You can check out his work
on GitHub. The library requires PHP 5.3.7 and later, which is well-distributed.
Bottom line
The
bottom line is that there’s no reason for you to be hashing passwords
yourself. You should be relying on a well-established methodology that
will help keep your users secure in the event of a data breach.
No comments:
Post a Comment