Secure authentication without SSL (part2)
February 21, 2008 12:20 pm PHP, Zend FrameworkAfter chatting with my colleagues, we noticed that my CRAM can be worth than nothing.
First, I have forgotten to precise what was the goal. It doesn’t prevent from stealing session by a man in the middle. The goal was to avoid seeing password on the network (if you use the same for all websites) and to prevent replay attack. The CRAM prevent replay by asking for a response with a different salt each time but it implies that the client and the server share the password. I was mistaken with this approach.
It’s a known and good practice to store a password hash instead of plain text password since a read access to the database doesn’t allow an attacker to authenticate since he sends the password in plain text and the server makes the hash. With my CRAM, even if you only have the hash, you can authenticate. That’s the security hole. Since you can’t prevent from a man in the middle attack without SSL, the CRAM seems useless.
But we still want to prevent replay and showing password. First, let’s come back to a basic authentication : we send username and password in plain text, the server makes the hash of the password and compare it with the one in database. To prevent the plain text exchange, we will store a double hash of the password in database : sha1(sha1(password)). The client sends sha1(password) and the server apply a new sha1 before comparing. Concerning the replay, we will use the CRAM. The server sends a unique salt for each try and the client still sends sha1(password) for authentication. The client will also send sha1(salt+md5(password)) as the challenge response. Then the server can authenticate the client with sha1(password) and ensure uniqueness of the challenge with the challenge-response.This implies to store sha1(sha1(password)) and md5(password) in database.
We have the best of the two approach. A man in the middle won’t see the password in plain text and won’t be able to replay the authentication because of the CRAM. He still is able to steal the session, but as long as it is valid. If the valid user logs out, the session becomes invalid. If an attacker has access to the database, he will find md5(password) and sha1(sha1(password)) what will allow him to answer to the CRAM but not to the basic authentication (which wait for sha1(password)).
This method remains low secure but I can’t see anything better without SSL. Like Bram sugessted, I should add a basic plain text authentication by default if javascript is disabled.

pepe :
Date: March 20, 2008 @ 10:39 pm
State of the art pw authentication should provide *mutual* authentication. iIeally, it will also protect against offline bruteforce attacks, as passwords tend to be rather short. An example for such a protocol is SRP.
See srp.stanford.edu. The SRP authentication also produces a strong common secret that you can use to encrypt your session or at least authenticate it, to prevent hijacking/replay
There are some efforts to integrate SRP into SSL, see RFC5054. This should also help implementing SRP somewhere else.
Your last sentence on the other hand seems to imply that you want users to authenticate via browser. use htaccess in digest mode(not basic). Its also ch-resp. but much more standardized.
have fun