For our web application, we want the client to be as thick as possible, and keep our server as thin as possible. The idea is to give the client all the necessary data, let the user interact with that data in a snappy Javascript application (currently GWT, but we are considering moving to Angular or Backbone). We would like to make the server completely stateless, which improves scalability and memory usage.
A fundamental problem of course is that there is some data a user is not allowed to alter. For example, when doing a password reset procedure, the user cannot change his username, because then he could alter somebody elses password. There is also a boolean that indicates if the user has passed the captcha, we cannot allow him to set that to true. And many other examples can be thought of.
The solution we thought of is the following: Together with these strings that a user cannot touch (we call them the priviledged information), we also add a signature. This is simply the concatenation of the priviledeg info, HMAC signed on the server with an AES key. When the data from the client returns we concatenate and sign the info again, and if the signatures are identical, we know that the client has not touched our info.
My questions: Does anybody see any weaknesses in this scheme, and can anybody point to resources (books, blogs) where more info about this subject can be found?
For anyone finding this question after several years: The thing I suggested was basically the same as Json Web Tokens (https://en.wikipedia.org/wiki/JSON_Web_Token). The idea I suggested was correct, but of course you should use established libraries instead of rolling your own.
Related
I want to implement an authentication system by following good practices, i want it as simple as possible and secured (im not going to implement some magic hashing function or something to feel a hero..) just wanting to use already known hash but not sure the right way of using it.
I read some articles on how Lastpass (a password management company) mange to handle their authentication and i loved their idea.So i wanted to implement my own authentication based on it.
Basically im creating an authentication key from the password on the client side (so the password is never sent as a plan text to the server).
that authentication key im sending to the server than do some hashing operations also in the server side and compare the result to the one inside the database.
On my client side:
auth_key = PBKDF2(SHA256, password+username, last_login_fe_salt, fe_rounds)
explanation - hashing password+username+last_login_fe_salt text fe_rounds times
last_login_fe_salt -> a random salt sent to the user once he/she input their username in text field -
To be honest, not sure how this last_login_fe_salt is efficent for the cryptography against Dictionary attacks but atleast two people having the same password will send different hashes on their network.
any hacker can get this data by asking from the server, i can add server side limitations (req/s if it makes some difference etc.. let me know what you think) also adding captcha might be a good idea. When a user logged in successfuly the server generates a new random string and saves in into the database.
*I didnt see any explanation which salt Lastpass uses on their client side hashing, they are using PBKDF2 algorithm that needs a salt parameter.
fe_rounds -> number of rounds given by the server when typing username -
its fixed for everybody and configurable by the server, also in articles i read about Lastpass they dont explain from where they receive the client side number of rounds...
so now we send auth_key as is to the server...
On my server side
now we are creating a new hash to compare the one inside the db.
Why another hash? if i understand correctly we bind the hash for server side data, like a combination of a password (that only the user knows) and server data.
db_auth=PBKDF2(SHA256, auth_key, user_be_salt, 100,000+user_configurable_rounds)
user_be_salt -> a random number that saved in db known only to the server and the ones who obtain the database, this changes on every successful login.
user_configurable_rounds -> number of iterations, every user can choose the amount of iterations (like in Lastpass) so attacker need also to guess the number or iterations?
I would be happy to hear what do you think about this authentication system, if its wrong than explain to me why and tell me what Lastpass do because i did not understand their entire authentication flow.
Most of what you're doing is useless from a security perspective. Lastpass has unusual security requirements -- don't treat them as a source of best practices.
If the client is responsible for hashing, and all of the parameters to that hashing are fixed, the hash effectively becomes the password. An attacker doesn't need to know the original password; they can simply pass the hash to the server.
Generally speaking, there is no way to verify a password over a network without either sending the password across the network (for traditional password authentication protocols), or having the server store the password in plaintext (for less commonly used protocols like SRP). Of the two, the former is preferable, as it's possible to secure the password in transit using protocols like SSL/TLS, whereas protocols like SRP require the plaintext of the password to operate.
Tweaking the PBKDF round count, either on the client or server side, is pointless. Set a fixed round count that makes the hash slow, but not so slow that it will place an undue load on the client or server. (100,000 rounds is probably excessive for a server-side hash. It takes roughly half a second to verify a password with those settings, so just two login requests per second would use 100% of one core on your server!)
Just recently I was wondering, how Google manages it with analytics to track the user but avoid any fraud (as kinda everyone could insert that JS into an HTML page).
Can anyone tell me, if they just resolve the Domain on each incoming request and validate if it corresponds to the correct account and comes from a allowed server (by looking up the IP)? If that's not the case, can anyone provide me some Idea on how Google could do this?
Google does not, by and large, avoid fraud at all. They offer an option to automatically filter for known bots and spiders, and apparently they intervened in some fashion against referral spam (which used to be a huge problem but has by now almost completely disappeared at least from the accounts I have access to).
Other than that, as you say, anyone can stick the javascript code into his HTML and send data to your account, or use the measurement protocol and not even bother with JS. Checking server IPs would hardly help (relevant here is the IP of the client and there are too many possible IPs for meaningful filtering).
Of course if you notice wrong data that follows a discernible pattern you can create filters yourself, which is at least gives you some control over what data is removed.
I am attempting to 'secure' (as I know it won't be very secure) the data in a indexedDB on the client side for an OFFLINE WEB APP (i.e. anyone who is attempting to access the data will be able to see the encryption method used so I am aware that makes brute force pretty damned easy!)
I am going to encrypt it using the Username and Password as that is the only thing I could possibly keep secret.
There are loads of ways to do this, however I have one requirement that has me stumped - I need to maintain the ability to be able to search the database.
Can anybody point me in the direction of how I can encrypt data but still be able to search it.
The encryption doesn't have to be bank-level security by any means, just want to protect the database in case a tablet etc. got lost so that 99% of people wouldn't be able to view the data directly.
You can try my library, ydn-db. For encrypted, you can only search by primary key only thought.
I got some of my nifty rails apps working, and its all jiffy and peaceful. I want to secure one tiny part that just feels wrong doing the way it is now - my sign-in procedure, where I use the form_tag with the remote option to send the content of a text and password field for obvious reasons using POST.
Sending a password just plain over HTTP makes me feel dirty. From where I can see, I have the following options:
learn to live with it and hope for the best
learn something awesome to have my controller doing magic through a rails-helper-i-dunno-about trick
build a separate app that runs on HTTPS and make life a living hell by going back to square one.
use JavaScript encryption
Somehow I think my best option is 4 - JavaScript encryption.
However, if the user types in his/her password and it gets encrypted with a part that is server-generated, it should be secure (in relation of solving the problem of sending it in plain text over HTTP) and solve my problem I guess. But on the rails side, to get that to work is to keep (yes, i have many things to cover, still) plain passwords in my database.
I need some help here - some pointers.
Why you should not use option 4: The risk of implementing something wrongly and putting your users at risk is much higher than when using something which already exists.
What you should do instead: Secure your users data by transferring it via https. Put
config.force_ssl = true
into config/environment/production.rb and you are ready to go. (Well and tell the webserver where appropriate certificates areā¦)
I have a quetion which may be simple/dumb or not :). In other words I have no idea if is fair enough or a completely foolish idea. Just some free thoughts.
What if I make my login via JavaScript with pass in it (yes I know), but pass will be hased by Secure Hash Algorithm. For instance:
I generate a pass with SHA which looks like
var = 0xc1059ed8... //etc
and paste into the code. There will be also two functions. One will compare two values (given by me with user's) and second will generate sha form user's input.
Is this could be safe theoritically or this is a horrible pattern and stupid idea? Can JS handle it?
EDIT: I didn't mean serious autentication like banking one. Just when I have my pics and want only to a few ppl to watch them and 99,9% of ppl on earth can't watch them :)
thx for responses
Sorry, no dice :) Secure authentication is not possible with client-side Javascript alone, because a positive authentication result could be faked. You will always need a server-side instance to authenticate against.
The common answer is that 'no, you can't do client side authentication' and for conventional scenarios that is correct, but I can think of at least two ways to make it work:
Use the SHA password hash to redirect to a static HTML page (0xc1059ed8...html). As long as the virtual directory doesn't allow file listing, no one will be able to guess the name of the file you want to protect. This gets clumsy really fast though.
Use an implementation of an encryption algorithm (AES, etc) in Javascript to decrypt a block of text that makes up the actual content of your page. Really only practical for one highly valuable page though.
Server side authentication is really the best, but it is incorrect to say that client side can't be done.
You cannot secure your site with Javascript alone. You will need some way to authenticate requests on the server.
Because all your javascript code is plainly visible to all consumers of your site. All a potential attacker would need to do is view souce of your website and they can bypass the password checking bit of your javascript and view the content behind it.
You need to have security implemented on the server-side, period the end. ASP.NET has a built-in way to do this called "Forms Authentication." Or you could use Session variables in a php script.
Your JS source will be visible anyway and anyone can fake it easily. You have to do a server side validation
Since the hash will reside on the user's computer (in the browser), i'd say it's a terrible idea. It will be easy to manipulate it.
You can use such a pattern to hide the password over a plaintext link and avoid https to login , but not as it stands.
The problem is that an attacker can steal the hashed password and use that to login to the server, and she does not need the real password.
This can be thwarted by a challenge response where the server sends with the page a "salt" : a big random number which is jumbled up with the password and then hashed, so the response is always different.
Unfortunately this has the effect that the server now needs to have plaintext passwords, which is a bad idea (ok, there are some tricks around this). So you might have to end up with a sending a salt, hashing your password, jumbling the hash with the salt by hashing it again and sending that to the server. The server hashes the stored hash of the password from the user db with the salt and compares both.
With security things get complicated real quickly and in complicated things opportunities lurk for the bad guys. A reason more to use well tested patterns, algorithms with a proven track record and libraries which have carefully implemented these.
And in any case it will be the server hwo has final say who can get access.
You'd be better off with no attempt at authentication at all -- at least that way you wouldn't give anybody the dangerous illusion that something involved might be secure.
Assuming you're dealing with a shared-secret situation, authentication is really pretty easy. You use a fairly simple challenge-response algorithm. Basically, the client sends a message to the server saying it wants to log in. The server responds by sending back a random number. The client encrypts that random number with the correct password, and sends it back. The server encrypts the random number itself, and compares the result to what the client sent. If they match, authentication has succeeded -- you've confirmed that the client has the right password.
The advantages of this: first, the password itself is never sent over the wire in any form, so an attacker has virtually no material to use in attempting to discover the password. Second, since the server generates a new random number for every login, an attacker cannot successfully authenticate by re-sending the packets it captured from a previous login.
Nearly any server with any sort of aspirations to security will already have something like this built in. It's purely a question of setting up your client to interact correctly with the form supported by the server(s) you care about.