I'm learning about web security, hashing and encryption stuff.
I'm building an authentication feature for an API REST backend app. I had an idea and i wanted to know your opinion.
What if we apply data validations on "clear" password that we are supposed to recieve from the client ?
From a backend perspective, accepting only password data in a bcrypt hash form. The password would have to be hashed by the front app, sended to the backend, hashed again to compare with the password in DB.
Scheme picture :
It could really increase the bruteforce load and time consumption and the clear/real user passwords would never go out from the user RAM.
I think it could be a good idea but i don't have enough knowledges to apply it blindlessly.
Related
This question already has answers here:
Is it worth hashing passwords on the client side
(13 answers)
Closed 2 years ago.
I'm reading a lot about security lately and something really bothers me.
I'm using Node.JS and I wanna store user data in the database. I currently hash the password on the server and then I save it to DB. But when the user sends data to the server he sends just plain text. I think that is the wrong approach. I'm using Bcrypt btw.
The method that I wanna use is: when a user need's to sign in I hash the password on the client, and then I send a hashed password with a salt to the server. The server then hashes the password again and stores the result in DB alongside with the first salt, that the user has passed. That means I have serverHash(userHash(userPassword)) and userSalt.
When the user then does log in, I wanna fetch him a userSalt from DB and hash his userPassword using that salt. Then I send userHash(userPassword) to the server and then compare userHash(userPassword) and serverHash(userHash(userPassword)).
Is this method good and secure, or is there a better way to do this, can I maybe use some third-party library or I can get away with this approach?
EDIT:
If someone bumps into this, don't do this, TLS will probably do the job, if not there are certificates that will help I think, I'm not 100% sure, but don't take my word for it but.
Purpose of Database Hashing Password
hashing password in server solve worries about accidental access to database.
where we consider server script are executing in a safe environment.
Authorized User can leak any data without protection
when a user login using username/password we will give him/her Authorization to Actions and view some Data .
if any crackers intrudes:
our server script
client browser or
intermediate media (network interception)
our goal (protect authorization) will be ruined.
so hashing the password on client-side dosen't solve any issue, if a
cracker can access to client-side area or intercept the traffic
data.
for example : an authorized admin, with heavy password protection mechanism,
can leak html data which tends to be admin-only viewable, if a cracker just intercepts network traffic.
Solution : Traffic Encryption
instead of sending hashed-password to server-side, The connection should get Encrypted like with SSL.
Todays Web Development
in Web Development its a good practice to to use HTTPS (Http+Ssl) when dealing with sensitive Data and Actions (scenarios which includes logins)
even in modern browsers, they show a Warning when dealing with html <input type='password'/> and not using Https.
I'm using scrypt to generate strong hashes of the password of the user. I want to log the user in, but don't want to send the password in plaintext over the wire, how do I check if the password is correct (without a roundtrip), since it is salted?
I'm having a client / server scenario. The client is an application on a desktop computer (not a website, nor http server).
How can I achieve this? I came only this far: I'm generating the the salt + hash on the client, form a mcf out of it and send it to my server. Save the mcf to the database. I haven't send the password, just the hash which is practically useless (since scrypt should be quite strong, and would require a few million years to reverse it).
How can I now log the user into my service, without sending the plaintext password to the server to compare it? I can't rehash it, since it would result in a different hash due to a different salt? I would need to send the salt to the client, hash the password, send the hash to the server, compare it, and send some authentication token back.
How can I achieve this? Is an authentication token actually secure? It can be simply used to impersonate anyone, I guess?
don't want to send the password in plaintext over the wire,
Good idea, but if the connection is not encrypted (something like SSL/TLS), then whatever you send is plaintext. If you hash a password client-side, and send it over the network, then THAT is the password. Some would say that there is no benefit here, but it does prevent the user from exposing their actual password, which they probably re-use on other sites. (read more here)
Ideally you would use something like SSL/TLS to encrypt the connection. I guess if that wasn't possible, using asymmetric encryption with certificates on the message itself that you are sending would be an ok way of re-inventing the wheel, but I am hesitant to recommend that without having a security person look over it. It's very easy to screw up, and the rule is never roll your own crypto scheme.
If you can't verify/invalidate/update the public key, then it is not a good scheme.
I would need to send the salt to the client, hash the password, send the hash to the server, compare it, and send some authentication token back
The salt isn't supposed to be super secret, but it's not great to just give it away like that, especially to unauthenticated users. The authentication token, hash, salt, etc can all be intercepted if the connection is not encrypted. Even if they couldn't, you didn't solve the problem of users creating accounts through this method (maybe you don't need to, but it is worth mentioning).
You have to use asymmetric encryption where only the server can decrypt the data.
There is no short answer to your question, because there are so many pitfalls that can happen if you do it wrong. But as Gray says, you do need TLS protection.
I have two sources that give you detailed explanations on the right way to do this if you want to do client side scrypt processing.
Method to Protect Passwords in Databases for Web Applications. If you do not want to understand all the rationale, just jump to section 4 to see the implementation (where PPF = your scrypt).
Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server.
They are slightly different solutions but based upon the same ideas, and either should be good enough for you.
In all the explanations I've read regarding Digest authentication they talk about password hash being saved already on the server.
What I'm asking about is the registration process how did that hashed password get there in first place?
Does that mean the implementation of Pre- digest authentication is open to one's imagination i.e while registration the server would generate a password and send it via email, or use an ssl connection when the user is registering only or what ? Is there some kind of standard process which comes with Digest authentication that I missed ?
Note: I'm not implementing I'm only studying; I know Digest authentication has weaknesses and there are better ways, I just wanted to have full image of the whole process.
Note 2: I notice someone voting to close the question "it's not programming question", I believe there is tiny misconception when I said I'm not implementing I mean in note 1 I mean not implementing in real production project, but I want to understand the concept of Digest authentication is implemented and my question is still as it clear and simple "how did the password got in the server in the first place".
Password of user is stored at server not the hasg. Each time a user wants to authenticate server creates a random variable(to prevent replay attack) and sends it to user . User uses the nonce and other details like url and realm to create a hash. Server does the same on its side and if these two hash match user is authenticated.
All this is done to prevent sending password in plaintext. sometime encrypted connection(ssl) is not available so instead of sending username password hashing is used. yes you are right password has to be shared out of the band say over phone or some other encrypted connection.
I am building a simple iPhone game which has a community maps feature.
Users sign up for an account with just their email and password, and then they can build, upload and download custom maps.
Now I know that sending the username and password with every request is usually a bad idea, but it is a lot easier for development instead of having to deal with login session, and I think it is okay for situations where security isn't a major concern.
The most important thing is to protect the user's password as they likely use the same password for multiple accounts.
So the simple approach I think is this: Send the user's username and password as one md5 hash with every request. Would this be okay?
Sure there is a risk someone might hijack the request, but login sessions have the same risk. And if a hacker got hold of a user's login session, don't they just need to force that user to log off so the client will send the user's username and password in the next request?
I haven't got any experience with mobile app development, however some general principles still apply. Firstly MD5 is flawed, don't use it. And if you are going to use a different algo (depends on your choice, and what what security/speed you are looking for, for thing like that I'd probably go for blowfish, but SHA512 should also do the job), definitely use salts.
I still think though that a simple session management would be better than sending the login information with every request, simple random session id should do (you generate it upon log in and associate with a particular user); of course there you run in a trouble with randomness of the ids (if they are predictable it is obviously a problem).
But I suppose the major point here is how will the app communicate with the server; if it is encrypted (HTTPS I would presume) you should be fine either way, I think is more important than whether you use sessions or hashed login info. And usage of HTTPS should take care of your worries about request/session hijacking as well (unless someone cracks the encryption with 200 modified PS3 units :) )
I don't want users to have to enter their passwords each time, and I don't want to store the passwords locally. When the user first sends me their username and password, I'm planning to send back some hashed version of their password (hash of pasword+salt), which will be put into localstorage to be used to authorize subsequent calls to our web services.
I'm aware that if my localstorage is compromised (e.g. stolen phone), the thief will be able to steal the token and make web service calls as the user, but at least they won't have the user's password.
Are there other vulnerabilities that I'm overlooking? Is there a reason to put it in a cookie instead of localstorage?
There are a few things to consider. You should use SSL to protect against eavesdropping. Otherwise any peer (someone else at the same insecure WiFi spot as your user) may be able to record your hashed password and replay requests with it. Also, the strength of the hashing algorithm is important. With a known username and a weak password it may be possible to generate a table of potential hashes and test that against the known hash (if the attacker manages to compromise the hash).
Regarding the difference between this and cookies, it's pretty simple. Cookies are usually randomly generated by the Server and aren't derived from the password at all. Other than that, cookies are pretty much a shortcut to what you're talking about. Whether you save it in your own storage within your app or to the HTTP library's built-in cookie handler, doesn't really matter. As long as you make sure to use SSL to protect against the eavesdropping/replay attack you should be pretty safe.
Also, I would recommend that you use a server generated hash so that you take the user password out of the equation completely.