I have a login form with username and password. I post this form data to a PHP file. For security reasons I want to encrypt my password in the database and network. Now I have done now following steps.

Get username, password from user and using HTTP POST send data to login.php

In login.php get these username,password and using MD5 Algorithm with salt to encrypt password

Store the username and encrypted password in database.

I want to know, is it the correct way or should I use MD5 algorithm in JavaScript (login form)? Or do I need to add MD5 algorithm in both JavaScript and PHP?

4 Answers
4

If we disregard the actual algorithm choice and consider the question: "Should I hash on both client and server side?"

Hashing in Javascript is completely unnecessary since the idea is to protect against the password being sniffed during transfer. But if that is a risk then the communication with the server is not secure which means that there could already be a man-in-the-middle attack going on.

This means that the javascript hashing algorithm could have been delivered by the attacker instead of the server. The algorithm could then for example send the password to the attacker.

So, no. You should not hash in the browser but instead use a secure connection to the server.

Or Simple do both, but as you point out, the level of security ( if it could be measured ) would not increase.
–
RamhoundJul 26 '12 at 10:57

1

@Ramhound My opinion is that extra layers like this: a) complicates the code and b) adds a false sense of security which may for example cause you to not consider other, real solutions.
–
Zeta TwoJul 26 '12 at 11:05

Hashing on the server and hashing on the client mitigate different attacks, and so one must consider which attacks one needs to protect against.

Server side hashing

Hashing on the server mitigates the compromise of the stored passwords (e.g. database leak). If passwords are not hashed here a successful attacker would have immediate access to the credentials, thereby allowing them to access the server. By storing hashed passwords the attacker is forced to spend additional effort in order to retrieve the actual credentials.

Client side hashing

Hashing on the client mitigates attacks on the channel between the client and the server, as well as on the server components which process the raw credentials (log in component, password set and change component). By hashing the password on the client the attacker is forced to spend additional effort in order to retrieve the actual password. Note however that this hash is a plaintext-equivalent -- if an attacker captures the hash they can use it to authenticate to the server.

The value here is in protecting the password which the user entered, since most users use the same password for other services. While capturing the plaintext-equivalent would compromise the user's account on your service, it would not compromise the user's accounts on other services. Obviously if all services used this scheme the same hash would be a plaintext-equivalent for other sites, and so a salt unique to one's service should be added here.

So what should one do?

The first class of attacks definitely must be protected against, since database leaks do happen, and so server side hashing is a must. The second class of attacks are largely mitigated by the use of TLS, and so the extra effort to use client side hashing is usually not worth it.

Hashes

As others have said, the use of MD5 and SHA1 are strongly discouraged. The SHA2 family of hashes are in themselves secure, but not alone appropriate for password hashing because they are designed to be fast. Passwords should be hashed with a scheme specifically designed for password hashing, such as bcrypt, scrypt or PBKDF2. If one of these schemes is really not an option, the password must be salted and iteratively hashed with a SHA2 hash.

Other approaches

There are schemes such as SRP which don't store the password or plaintext-equivalent on the server, nor transmit the password or plaintext-equivalent between the client and server.

You shouldn't use MD5 at all. It's been effectively cracked, and is about useless for secure hashing. Even on a regular computer these days, you can generate MD5 collisions in a few seconds. SHA-1 is also fairly insecure these days (though still a bit tougher than MD5, it's not too hard to generate collisions on either), so you should be using [at minimum] a SHA-2 based hash algorithm (SHA-256 or SHA-512).

Specific implementation strategies don't matter a whole lot if you pick a hash algorithm than can be compromised in minutes by anyone with the ability to search for "MD5 cracking" on Google.

-1. There are no known collisions for SHA1. It's insecure for passwords because it's fast, and suffers from length extension problems. You should also not use SHA-2 family for storing passwords, because they're too fast. You should use a slow key derivation function such as bcrypt or PBKDF2.
–
PolynomialJul 26 '12 at 12:08

1

<sigh> eprint.iacr.org/2008/469.pdf A 2008 attack creating collisions in 2^51 operations. And there was news this year (maybe even this month) about it being weakened further, so your statement is blatantly false. SHA-1 is compromised, and essentially insecure. Please be more careful next time, lest you spread dangerously incorrect information around.
–
HopelessN00bJul 26 '12 at 17:11

2

@HopelessN00b The results you cite are about finding collisions (i.e. finding A and B such that hash(A)=hash(B)). This is not useful for password cracking: what you need there is preimage resistance (resistance against finding P such that hash(P)=E, given E). MD5 remains effective against pre-image attacks to this day. While it does not have the security that was intended, and further attacks are expected in the years to come, a preimage search still takes prohibitive time (2^116 according to Sasaki and Aoki 2009).
–
GillesJul 26 '12 at 18:28

2

@HopelessN00b I -1'ed your answer because the potential weaknesses of SHA1 have nothing to do with the reason we don't use it for password storage. I reiterate: There are no known collisions for SHA1. There are known weaknesses in SHA1 that could allow you to compute a collision in <insert huge number> operations. SHA1 is not broken until a real collision, i.e. a pair of two plaintexts that produce the same hash, is found. Using SHA1 is bad practice because it's considered weaker than SHA2 variants, and may fall to practical attacks later. However, you shouldn't use SHA* for passwords.
–
PolynomialJul 26 '12 at 21:15

You need to send the password to the server. If you first take the MD5 of the password and send that to the server, then the MD5 effectively becomes the password: if the attacker finds the MD5, they would be able to log in, without needing to find what it is the MD5 of.

Thus you need to make sure that your Javascript code (the part that runs in the browser, i.e. the client) reads the password and sends it to the server, where it will be processed by the PHP code. Make sure that the password input field is declared as a password, so that the browser will offer to save it in its password database and not in the regular history.

To avoid an attacker finding the password in transit, or impersonating the server, you must use HTTPS. HTTPS encrypts the connection and lets the client verify that it is talking to the intended server and not to an impersonator who is trying to grab users' passwords. Furthermore, you should use HTTPS to transfer any data that depends on the password: otherwise an attacker could let the user log in, then hijack subsequent transmissions.

On the server side, in your PHP code, do not use plain MD5 to hash the password. Vulnerabilities that allow an attacker to obtain the password database are very common (a recent example — with a thread you should read), so don't plan on this never happening to you. The most important thing is that you must use a salt, because having a unique salt for each stored password prevents methods that attack a lot of passwords at once: essentially, when passwords are salted, the only way to recover them from the password database is by trying each possibility (brute force). (See Why is using salt more secure? for more details.)

Furthermore, MD5, while not completely broken (yet), has a lot of known weaknesses. Don't use it for anything; use SHA-2 (SHA-256 or SHA-512) instead. For passwords, this isn't ideal, because a good password hashing function is slow: the legitimate server doesn't spend much time on password verification, so you can afford it to be slow; but an attacker working from a password database spends all of his time hashing passwords, so a slowdown will hit him hard. The general recommendation for password storage is Bcrypt or PBKDF2 — see Do any security experts recommend bcrypt for password storage?