views:

343

answers:

9

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 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

A: 

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

quoo
And yeah, don't store the actual password ANYWHERE.
quoo
I think encryption is a deceiving word here. It's "cryptographic hashing", not encryption. Encryption sounds like simply encrypting the password vs hashing which cannot be "reversed".
xyld
Passwords should always be hashed. Encryption should never be used for passwords.
Rook
ah, thanks, corrected, for some reason i thought hashing was a more specific type of encryption. but then.. i'm a front end dev, i don't deal with this stuff too often.
quoo
+2  A: 

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.

Steven
... or stored anywhere for that matter.
Steven
md4, md5, sha0 andsha1 are broken hash functions. Anyone who purposes a vulnerability will get a -1, sorry its the rules. sha256 should be used.
Rook
You must have it in the memory when you check it, unless you hash on the client side in javascript. Not that it matters - if an attacker can access the memory, having the password there will be the least of your worries.
Tgr
@The Rook, if sha0 is broken, so is sha256. The only difference is the key length.
Malfist
A: 

if you were asking will this code check the password stored in the database - yes, it will.

Col. Shrapnel
Clearly this isn't what they were asking.
quoo
+10  A: 

See this: http://stackoverflow.com/questions/401656/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

xyld
+1 for first to mention hashing. **HASHING IS NOT ENCRYPTION PEOPLE** - they are completely different concepts *(it is also not the same as a checksum, which is not necessarily cryptographically secure)*. Also, **MD5 is completely broken**, don't use it.
BlueRaja - Danny Pflughoeft
+1 for mentioning that MD5 is broken!
xyld
Okay, then hash is a function of php I guess? Do you have an acutal example?
Camran
Do the downvotes have anything to say here? Or do I just get downvoted without explanation?
xyld
@Camran - See the question Kendall Hopkins linked to in the comments of the original quesion.
MiffTheFox
Really don't like how some people respond to the person asking a question on my answer and downvote my answer. If you have a link to redirect the asker, ANSWER the question, don't just comment, worse don't downvote people that DONT know about that other question.
xyld
@BlueRaja you have a good chance to demonstrate an md5 weakness. Not with many words but with just single one. If you please: http://stackoverflow.com/questions/2768248/is-md5-really-that-bad
Col. Shrapnel
A: 

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.

Banjer
-1 encryption should never be used for passwords. This is a clear violation of CWE-257 (http://cwe.mitre.org/data/definitions/257.html) A message digest function such as sha256 should be used. Anyone who purposes a vulnerability gets a -1, thats the rules.
Rook
-1 for The Rook for saying encryption should never be used, then citing CWE-257 which says "Use strong, non-reversible encryption to protect stored passwords."
Stephen P
A: 

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'])
Gazler
-1 md4, md5, sha0 andsha1 are broken hash functions. Anyone who purposes a vulnerability will get a -1, sorry its the rules. sha256 should be used
Rook
Fair enough, could you please provide a source?
Gazler
BlueRaja - Danny Pflughoeft
+1  A: 

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).

Tgr
md4, md5, sha0 and sha1 are broken hash functions. Anyone who purposes a vulnerability will get a -1, sorry its the rules. sha256 should be used
Rook
+1 Best answer so far. @The Rook: That seems a bit unfair, sha1 isn't nearly as broken as the other three (no collisions have even been found yet)
BlueRaja - Danny Pflughoeft
@BlueRaja can you show us a MD5 weakness using a collision please?
Col. Shrapnel
@BlueRaja, your right but there are 2 attacks against sha1 and it should be within reach. This post is still a technically a cwe violation. And yes, I am prick :)
Rook
Finding a collision in sha1 takes about 2^60 operations (instead of the 2^80 needed for a brute force attack). Get a good computer with 4 or 6 cores, and you are done with it in three years. You can call that broken in some technical sense of the word, but saying it is not good enough for a classifieds website is just stupid. Especially since there is no better option available in vanilla PHP (you need [hash](http://www.php.net/manual/en/function.hash.php) for sha256, and few hosts allow installing PECL extensions).
Tgr
Rook
Let's assume 1000 operations for a single sha1 run. That means you can do about 10^16 sha1 runs in the time needed to generate a collision, which is enough to brute-force test all passwords shorter than 10 characters (upper+lower+digit). Few sites require passwords longer than 8 characters. Not only is the attack you are proposing implausible, there are less implausible attacks which work against stronger encryptions as well.
Tgr
Furthermore, it is not obvious that attacks which work against a pure sha1 hash also work against a salted one.
Tgr
Moved this discussion into a separate question: [Is SHA-1 secure for password storage?](http://stackoverflow.com/questions/2772014/is-sha-1-secure-for-password-storage)
Tgr
+4  A: 

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.

Marcus Adams
A: 

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 
 }
crrodriguez