I'm sitting here and working on a small project, in this case it's between PHP and Obj-c.
What is best practice for secure authentication between these?
something like
myhost?do=login&user=my_username&password=my_password
feels a bit unsecure since the username and password is posted open.
I guess i could do some SSL for this(?), but does any one have another good example for a good solution?
My thought is that a login sets a auth_key to the user table (MySQL) and if the above GET-variables are correct, it will return userid and this auth key. Then on every thing i do against the PHP, this auth key is updated and returned to the user (obj-c program) and everything that is done on the server is authenticated against this key, this just for not "showing" the password every time and when a key is used, it's useless since it's renewed...
This, however, can't stop anyone for doing this manually since the key is recieved and updated on a login.
Any ideas for making this more secure, or am i just paranoid?
The distinction between GET and POST doesn't actually matter - both are HTTP requests, and as long as you don't encrypt your data, the plain body of the request can be sniffed.
Of course a login should be as a POST req, but just because it is not idempotent, and may have side-effects [db writing, session start, and so].
You may just want to switch to SSL over HTTPS protocol to be sure your data is safe.
As a [really] minimum protection, you may use Basic HTTP Auth, which encodes login credential in Base64 before sending them - you can do this easily with RestKit.
Use POST for username and password forms along with SSL
Related
Say I have a PHP application and want the users data to be encrypted before it it gets to the server (to prove to users that their data will not be data mined or resold for advertising).
Similar question was asked here ( Secure Javascript encryption library? ) and implies that this is not going to work, but with the increase in privacy interest amonsgt users this requirement is only going to get greater over time.
Example, using the Stanford library (http://crypto.stanford.edu/sjcl/) a web form has an additional ‘long’ password field which the user pastes in (probably from email for example)
sjcl.encrypt(txtPassword, txtFormFieldToBeEncrypted)
The encrypted data is sent to the PHP page, and the process is reversed when the page is loaded.
Would this work if the users used Chrome or another browser that remembers form values - obviously this is not a secure result, but would this be effective enough to keep the users information private from the host server?
EDIT: Just to be clear, I am only interested in making the information invisible to the host server, and understand that this solution wont protect from 3rd party attacks
Protection on the page is useless, for the simple fact that the encryption key / mechanism will also be in the scope of the page and can thus be tampered with by a malicious party (or by the user itself when inspecting the page).
To avoid data going over the line unencrypted there is also no reason to "roll your own"(tm), because for that there is SSL.
If you want to make sure that the data that you receive on the server was actually originating from a page that you control, you can rely on CSRF protection.
First of all use SSL it is for an only way for secure communication. If you make encryption in JavaScript it is trivial to decrypt your message (because all your code with keys is public).
If you worry about CFRS attack use anti-forgery token (more here: http://bkcore.com/blog/code/nocsrf-php-class.html)
It's perfectly possible to do this, Lastpass for instance built their business model on it. All their server does is store an encrypted blob which they cannot do anything with, all encryption and decryption happens on the client; including a Javascript implementation in the browser. The entire blob of encrypted data is downloaded into the client, where the user's password decrypts it; and in reverse on the way back up to the server.
So if your question is whether it's possible: absolutely. It's also a lot of work, since you will need to be providing the same en-/decryption code for as many platforms as you want to support. You'll also need to secure every context where that code will run, to prevent third parties from injecting code which would allow them to access the client side decrypted data. So, everything needs to go over SSL with no 3rd party content being allowed to be injected.
Here are a bunch of reasons why javascript encryption in the browser is almost always a bad idea.
You need to think deeply about your trust model. Do the users trust the server? If not, there is no hope for trustworthy javascript crypto since the crypto software itself comes from the server. If the users do trust the server, why does the data need to be encrypted client-side? Just use SSL to secure the connection, then have the server encrypt the data before storing it.
I am trying to implement a web service and need some (very) simple Authenticate to restrict access to the service.
I found out about HMAC and I think I understand how to implement it. But I have a couple of questions in mind.
Let's say I have this HTML Form on the consumer side. When making a GET/POST request to my server.
Is is enough to create a hash of: public_key using the secret_key?
OR, do I need to create a hash of the entire POST variables/array?
I'm thinking it would be enough to send the hash of the public_key only but just wanted to make sure and ask you guys.
I am planning to do this:
Create a hash of the public_key
Put the hash in a hidden field or in the URL as a param together with the public_key (or client_id) and other POST/GET variables.
Receive on my server and verify the hash against the database by recreating the hash of the public_key using the secret_key.
If the hash matches, I accept the POST/GET requests.
Your thoughts?
Clarification: public_key is like the client unique id where I can use to identify what secret key to use to generate the hash on the server.
The pubkey is just used as an alternative way to recognize the user. It could be the user email as well, by the way since you don't likely want to expose your user data to their programmer (or to potential sniffers) you create a unique identifier for each user. It's all it means. Then you need a private key to sign your hash.
Of course to make it worth it you have to sign all unique request data, otherwise someone could alter your request body and you wouldn't be able to detect it (MITM attack).
You also should care of creating a timestamp that must be included in the HMAC itself, then pass it alongside with the request. This way you can make the signature expirable and so you are not exposed to replay attacks (someone steals the request and without modifying it replies it against the server, operating multiple times the same action... think what a problem if it's a request to pay for your service, your user would be very very angry with you).
Also remember (nobody does) to encrypt also the Request-URI inside the HMAC itself and also the HTTP method (aka verb) if you're using a RESTful webservice, otherwise malicious users will be able to send the request to other URIs or (using RESTful services) change the meaning of your request, so a valid GET can become a potential DELETE.
An example could be: user wants to see all its data, makes a GET request, a Man in the Middle reads the request and changes GET with DELETE. You are not given the opportunity to detect that something has been changed if it's not inside your HMAC you can check about, so you receive a DELETE request and boom! you destroy all user data.
So always remember: everything is essential to your request must be validable
And if you rely on a HMAC then you must encrypt everything you need to trust the request.
Also always remember to start designing your system by denying all request, then if you can validate them perform requested actions. This way you always fall back on denied requests. It's better to have a user email telling you that he cannot do something that have your user data propagated on the net.
Use TLS. It fixes this and a host of problems you haven't even thought of yet.
I have a server with mysql information stored on it. Now i need my Iphone application to be able to log in to a account and update information stored in the the database. So i was wondering, what would be the best way to go about this?
Shall i just use POST to send data to a PHP script and then echo a response for wether the user can login or not(The username and password match) ?
It's just this seems unsecure, also do i need to create some kind of session once the log in stage has been completed?
I have never done this before, so would be really grateful of any help!
Thanks very much
You described the common way to do it. You need some sort of a webserivce you can "talk" with. It's done in the way you post the data to the webserivce, the webserivce (e.g. written in PHP) opens a connection to the database and returns wether the request/login was successful.
If you just send the password in clear text, than it's unsecure you are right. I use two things to make the communication more secure.
SSL: If possible make a secure connections. But it's possible that you do not have the option to connect through ssl.
Password hashing: You can at least hash the password. In a normal case the username is public in an application, but the password isn't. A hashing function is function that returns a string that looks a little bit random to humans. Hash functions are one way functions. There's no way to go back to the original string (if you don't have a few super computers and a few hundred years of time). So once you retrieved a hashed password within your webservice, just hash the password in the database too and compare them. A string always returns the same hash if you use the same hash function. Common hash functions are: MD5 or the SHA familiy
I hope my answer helps you any further. Perhaps my approach is not the most secure, but until know no one told me anything better. ;-)
For phone apps, desktop app and some web apps this is a common issue.
Sandro Meier (above) said correctly that if you have SSL access then this is best way to send via a HTTP POST a username and password so anyone else on the network cannot sniff these details.
If you cannot use HTTPS, then I would recommend from your iPhone app.
1. post username + password to the PHP from the iPhone.
2. ON the server in PHP code, check these details, if correct generate some random token eg (KHnkjhasldjfoi&*) you can do this by using the MD5 hash function in PHP.
3. Save this hash in the db so you know which user you sent it back to.
4. Now for all other requests from the app to the PHP include this token with the request (in PHP you will need to check this token and if it is valid, then fetch or update data).
5. This way if someone is trying to sniff the connection they dont have access to the users password, they can only steal the token.
If you want to be 99% secure you need to use a HTTPS connection (but HTTPS can be faked, I wrote about this in Computer World).
The pervious person mentioned using a MD5 hash to send the username password, but this also can be hacked (a user could download you app, find the salt to the MD5 hash and that way they could still steal any password). I think the W3C said that they do not recommend encrypting web forms and password pages as it gives a false sense of security because pretty much anything can be decrypted (I think a Quantum computer can even decrypt HTTPs), they recommend using HTTPs as it provides the most security for sending sensitive data.
W3C Passwords in the clear.
http://www.w3.org/2001/tag/doc/passwordsInTheClear-52
I'm making an Ajax login system and i wonder if this is secure
Post the username and the password with ajax
Check the login server side, if valid, return the new session id and the user id in a JSON string
Get the JSON with javascript then create the session's cookies "session_id" and "user_id"
Call the page where the logged user is redirected with AJAX
Thanks
Secure for 08/15 website: yes
Secure for online banking: no
The method you use is equivalent to an unencrypted everyday login <form>. Albeit you should really not rely on a "user_id" cookie. Rather save the verified user_id in the session store only.
Also you might try to simply return the session cookie on the JSON result for the AJAX call. It usually sticks to all further HTTP requests, so you don't need (3) to set the cookie via Javascript additionally.
Creating a secure login system is HARD. I would just like to name a few things that could go wrong(bite you in the ass):
unsecure connection(http instead of https).
XSS
CSRF
SQL-injection
unencrypted passwords or simple md5 vulnerable to rainbow table attack.
There a lot of free secure login systems(created by security experts) which you should use instead, for example:
facebook connect
google friend connect
twitter single sign on
openid
I think it could be secure when use post in step 1. already ciphered password and little bit ciphered username, to avoid simple attacks.
Like send(base64_encode(username),md5(password));
And another word, you should check valid session id on server-side, not on client-side in app.
You cannot let client-side script (which could be altered by adv. user) to check session validity.
It's like creating nice and secure API, you have to check everything on server and don't let any dangerous (setting/deleting/creating methods, etc..) opened wordlwide.
I can think of several problems with this idea, in direct order of importance (least to most):
1) Your site won't work for those with JS disabled.
2) Your site may not show the in-browser yellow toolbar to notify the user that SSL/HTTPS is enabled. (Depends on implementation).
3) The user_id parameter is not required client side, and probably not a good idea either. Authentication tokens are almost always just a single identifier, and that's all that is required to prove a user is logged in.
4) It's usually bad practice to write your own authentication capabilities. I know you are not replicating the back-end (which is a very bad idea), but most frameworks already automate the front-end authentication for you and do a good job at it. Use those frameworks, cause they have been tested and are secure. Also, a lot of the time the framework will help you (eg. make it easier to switch authentication providers).
I am researching ways to secure a javascript application I am working on. The application is a chat client which uses APE (Ajax Push Engine) as the backend.
Currently, anyone can access the page and make a GET/POST request to the APE server. I only want to serve the chat client to registered users, and I want to make sure only their requests will be accepted. I can use username/password authentication with PHP to serve a user the page. But once they have the page, what's to stop them from modifying the javascript or letting it fall into the wrong hands?
This method for securing a client/server application looks promising: http://abhinavsingh.com/blog/2009/12/how-to-add-content-verification-using-hmac-in-php/
I have another source that says this is ideal for a javascript client since it doesn't depend on sending the private key. But how can this be? According to to the tutorial above, the client needs to provide the private key. This doesn't seem very safe since anyone who has the javascript now has that user's private key. From what I understand it would work something like this:
User logs in with a username and password
PHP validates the username and password, looks up the user's private key and inserts it into the javascript
Javascript supplies a signature (using the private key), and the public key with all APE requests
APE compares the computed signature to the received signature and decides whether to handle the requests.
How is this secure if the javascript application needs to be aware of the private key?
Thanks for the help!
The answer: You technically cannot prevent the user from modifying the JavaScript. So don't worry about that because you can do nothing about it.
However, the attack you do need to prevent is Cross-Site Request Forgery (CSRF). Malicious scripts on different domains are capable of automatically submitting forms to your domain with the cookies stored by the browser. To deal with that, you need to include an authentication token (which should be sufficiently random, not related to the username or password, and sent in the HTML page in which the chat client resides) in the actual data sent by the AJAX request (which is not automatically filled in by the browser).
How is this secure if the javascript application needs to be aware of the private key?
Why not? It's the user's own private key, so if he is willing to give it out to someone else, it's his problem. It's no different from giving out your password and then saying someone else has access to your account.
If you think about this a bit, you'll realize that you don't need to implement public-key encryption, HMAC or anything like that. Your normal session-based authentication will do, provided the communication channel itself is secure (say using HTTPS).
HMAC authentication is better served for an API that third parties are going to connect to. It seems like your app would be better served by writing a cookie to the client's browser indicating that they've been authenticated. Then with each ajax request you can check for that cookie.
Edit: I take back a bit of what I said about HMAC being better served for third party APIs. Traditionally with HMAC each user gets their own private key. I don't think this is necessary for your application. You can probably get away with just keeping one master private key and give each user a unique "public" key (I call it a public key, but in actuality the user would never know about the key). When a user logs in I would write two cookies. One which is the combination of the user's public key + time stamp encrypted and another key stating what the time stamp is. Then on the server side you can validate the encrypted key and check that the time stamp is within a given threshold (say 10-30 minutes in case they're sitting around idle on your app). If they're validated, update the encrypted key and time stamp, rinse and repeat.