Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a secured WebService from jQuery safely

I have a WebService which has several calls which are only available to members of the site. I want to build a pure html/jQuery mobile app which can call into this service make requests and download information.

My initial plan was to put the users' username and password in the auth header but I'm worried about exposing them to any traffic sniffers. I can obviously create a session key so after the initial authentication they call in with a token but this may be vulnerable to session stealing.

My current plan is:

  • Implement a Login call, this will return a token which will expire after a designated time
  • The JS calls in with this token (thereby reducing the number of times the password is sent).
  • The user makes their calls
  • The token is compared against the user's IP address.
  • The user logs out, this ends the session and removes the key early to reduce risk

Another thought was to encrypt the password as I send it. Is it possible/sensible to do public/private key encryption in JS based on the .NET RSACryptoServiceProvider implementation?

What is the best approach to handle authentication, ideally without purchasing an SSL certificate (the data itself is not particularly sensitive). ?

like image 974
Liath Avatar asked Jun 02 '14 07:06

Liath


1 Answers

Apart from obvious reasons why SSL is highly recommended, and you should definitely use it if it's possible, you can consider rising your security by hashing your login and password.

Hashes work in a way that is very difficult to break - hashes of very similar strings are completely different, even if you only change one char. See that:

Login: "jacek", SHA1: "9749d1492af3d43f9c09e04c5c43f27bb909af51"
Login: "Jacek", SHA1: "46c676716f0e9aa86545c034d0e22a114d7cd488"

This shows that you need an EXACT password (or it's hash collisions, which are difficult to compute) to 'break' the hash, and a 'simmilar' one is completely useless.

Your implementation may go like that: When you create a user (f.e. registration moment), you compute hash of login and password. After that, in DB you will have:

Login  | HashedLogin                              | HashedPassword 
---------------------------------------------------------------------------------------------
jacek  | 9749d1492af3d43f9c09e04c5c43f27bb909af51 | e4e088f4eaa96db85e11ba491a189f96f2e11793

(You may keep an unhashed login for debugging / maintanence purposes only.)

After that, before you conect to Web Service in your app, you do exactly the same, but in jQuery:

var _HashedLogin = Sha1_Hash($("#login").text());
var _HashedPassword = Sha1_Hash($("#password").text());

There are lots of third-party SHA1 libs, use any of them ;)

Then, when you send info to your webservice, send the hashed values only. Even if someone sniffs your ajax call, he will only get something like:

"UserInfo":
{
    "login" : "9749d1492af3d43f9c09e04c5c43f27bb909af51",
    "pass" : "e4e088f4eaa96db85e11ba491a189f96f2e11793"
}

This is useless for the thief, but you can easily compare those values with your precomputed hash in the database. You can run

select id from Users where HashedLogin = 'login_from_your_ajax_call' and HashedPassword = 'pass_from_your_ajax_call';

If you get any result of this query, your secured verification is completed and you have the Id of a user. If there are no results, the login or password is invalid.

SHA1 is quite secure for home and semi-pro reasons, to compute a hash that will collide your password, you may need up to 2^61 comparisons. It would take literally YEARS for a home computer to break that. This solution is still vulnerable to the man-in-the-middle attacks, but is a leap of security from sending plaintext authentication data.

Also, REMEMBER that even once the user is authenticated, unless you use SSL, ALL the other (client <-> Web Service) connection is still insecure and easy to sniff.

like image 155
Kamil T Avatar answered Oct 08 '22 23:10

Kamil T