Password verification; Is this way of doing it safe?
I have a classifieds website, where everybody may put ads of their products.
For each classified, the user has to enter a password (so that they can delete the classified 开发者_JS百科whenever they wish).
So basically, when somebody wants to delete a classified, they click on the classified, click on the delete button, and enter the pass.
I use MySql as a database.
I use this code basically:
if ($pass==$row['poster_password'])
where row[poster_password] is fetched from MySql...
What do you think? Thanks
See this: Secure hash and salt for PHP passwords
Hash their password (maybe with some salt) on the way into the database. Store their hashed password in the database (NOT their actual password). Then fetch their hashed password from the database and hash their input password and compare the hashed passwords.
Some lame pseudo code:
password_hash = hash(password_cleartext)
# store password_hash in database
Later:
input_password_hash = hash(input_password_cleartext)
fetched_password_hash_from_db = fetch(db, password_hash)
if (input_password_hash == fetched_password_hash_from_db) {
... authenticated ...
}
For a start with php, try: http://php.net/manual/en/function.sha1.php
Your code looks safe, but your design may need some work.
SQL Injection
The dangerous part of the code is in storing anything in the database, or showing anything to the users, that is collected from the user. So, the part you have to be careful with occurs prior to your example. Ensure that you're validating, filtering, and escaping any data that you collect from the user, including the password and the ad information.
Encryption
The advantage of storing the password in the database is that you can let the user retrieve the password via email or some other means if they lose it.
However, if you do store passwords, you should store them encrypted, using a secret key, so that if someone is able to direct read access to your database, they can't read all the passwords in plain text. Still, you're going to have to store the secret key somewhere, and if someone gets your secret key and has access to your database, they will have access to all of the passwords.
Hash Values (recommended)
It's best practice and more secure to only store one way hash values (SHA1 or SHA256) of the passwords in the database instead of the actual passwords. This way, you cannot retrieve the password. Hash values are intentionally one way by throwing away some of the data.
Instead of retrieving the original password, you hash the password that the user enters and compare the hash value against the stored hash value to see if it matches. If the user loses the password in this case, instead of emailing the password to the user, you email the user a new, randomly generated password.
Storing only the hash value protects your data even further, since even if the user has read access to your database, the hash values offer no advantage, and there is no secret key that will unlock all of your hash values.
When you hash the passwords, be sure to use a random salt value and store the salt to protect your list of hashes against rainbow attacks.
Summary
Sometimes you don't get to choose the password. Sometimes the password comes from another system, so you don't always have a choice, and sometimes your superiors (maybe even the users) will demand that they be able to retrieve passwords, however, when possible, you should choose the more secure option.
Note that all of this encryption and hash value business only partially protects your server against people who are able to obtain read only access to your data. Sometimes, getting your data is enough of a prize, so if the user can read the password hash, can they read your credit card numbers?
You need to protect your database. Do you have a secure password on your database system? Do you only allow local access to your data? Have you created a database user with least privileges to use in your application? Are you properly protecting yourself from SQL injection and scripting attacks?
If someone has read and write access to your data, the whole password business becomes moot.
Don't store the actual password in the database. Instead store a checksum (MD5, SHA1, etc). When you want to compare, perform a checksum of the value the user submits and compare the checksums.
That way you never have the actual password in memory.
Best practice is to keep a salted sha1 hash in the database:
if (sha1($pass.$row['poster_salt'])==$row['poster_password'])
(poster_salt is a random string generated and saved when the user chooses the password.)
That way if an attacker gets access to your database, they still won't get the passwords of the users (which are probably used elsewhere too - most people don't bother to choose different passwords for different sites).
Also, you should use secure (HTTPS) connection. And require sufficiently strong passwords.
(At least if you want good security, which might be an overkill in the case of a simple ad listing).
I would encrypt the password before storing it, then decrypt when retrieving it so you can check it against what the user entered in plaintext (per your example code above).
Also, protect yourself against any SQL injections, or someone could see all the passwords (and other data) in your database.
This implies the passwords are placed into your passwords unencrypted. If this is the case you should be using some sort of encryption when entering the passwords. One way of doing this is the MD5 function which hashes the password.
When doing the insert you would do
Insert into table(email, password, whatever) values('$email', md5($password), whatever)
And when comparing you would do
if (md5($pass) == $row['password'])
You should hash the password somehow and store and compare using the hashed version. See this link for more details:
http://phpsec.org/articles/2005/password-hashing.html
my suggestion is the following
the users table have two columns, one called "password" and the other "salt"
$password = 'youruserpassword in plain text';
$salt = bin2hex(openssl_random_pseudo_bytes(32));
$passtostore = hash_hmac('sha384', $password, $salt);
insert into users(password, salt) values($passtostore, $salt);
Then to verify if the user has entered the correct password...
retrive both password and salt from the database and
if(hash_hmac('sha384',$userpass, $row['salt']) === $row['password']) {
// is valid
}
精彩评论