1

I currently have a desktop application which requires the user to have a username and a password. These credentials are stored on a webserver (myserver.com), so when he types the username and the password and clicks on the Login button, they're sent to the webserver. If the credentials are right, the server will return "ok", some user info, and the main form will be displayed. If not, the server will return "wrong" and an alert will be displayed. However, this is very insecure, because a user can just edit the hosts file, redirect myserver.com to his localhost, which always returns "ok", and bypass the login screen. I was told to generate a pair of RSA keys, and then encrypt a "nonce" (a random number) in the desktop app and send it along with the credentials. If the server could return the number decrypted, that would mean that it's actually my server. I have to say that the webserver is hosted in Heroku so HTTPS is enabled by default, but I don't have any SSL certificates whatsoever. This seems to be pretty good, but is this prone to a man-in-the-middle attack? An attacker could just redirect myserver.com to his localhost, send the request from localhost, receive the decrypted number, change "wrong" to "ok" (or change some user info) and send it back to the app.

How can I make a more secure login form for a desktop app?

1

Sprinkling crypto fairy dust will not prevent the attacker who controls the client from making the client do anything s/he wants with it. S/he can still redirect it to localhost, but now needs to replace the public key you embedded with the app with his/her own public key. Or attach a debugger and disable the use of crypto entirely. Or decompile, remove use of crypto and recompile. You can't control this, because it is all running on the client computer over which your attacker has total control and you have no control, and trying to control it is a losing strategy.

What you need to do is keep the assets that the user wants to access on your server, so it doesn't help him/her to change the client's behavior. If the client connects to localhost instead of your server, they can't access the assets since the assets are on your server, not on localhost. If they try to access services for which they have not yet logged in, your server should reject the request - after all, your server should be tracking who has logged in with a standard session management implementation (don't write your own; it's too hard and writing one's own always results in a vulnerable implementation).

Oh, and you do need to use crypto, but only where it actually helps. Use TLS 1.1 or 1.2, or use SSHv2 to protect the network traffic. Select strong ciphers. Provide your users with your public key digitally signed by a trusted certificate authority. Encrypt the assets when you store them in your database. Use strong crypto like aes128 or 3des. Generate your key securely, reading the complete documentation about your random number generator, only using one that says it's ok for cryptographic purposes, that is standard, and without taking any chances that you might overwrite the seed instead of supplementing it (some documentation is very misleading, like Java's java.security.SecureRandom).

And finally, either hire a security expert or go learn about security yourself on OWASP.org (a great place to start, but be careful, because they often have mistakes, themselves).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.