From a lot of posts I've seen on the site, logins performed by AJAX or traditional forms are just as secure as one another. (re: Login/session cookies, Ajax and security Ajax login and javascript cookies, is this secure?)
My question(s) is/are:
If I hash the user's password (via client-side/javascript hash
libraries) before I send it to the server, do I increase security from people easedropping?
If I put a form token (one random based, another time based), does that cover CSRF attacks?
Would I have all my bases covered after all this? Would this form be secure?
Actually this could be a major security problem. The reason why passwords are hashed is a means of planning on failure. An attacker might gain access to the data store (sql injection) and then obtain the hash. If you are just logging in with a hash, then the attacker doesn't have to crack the recovered hash in order to gain access to the application.
Replay attacks are also a problem. If I sniff the hash during authentication, whats stopping me from just replaying that request to authenticate?
Protocols that use message digest functions for authentication provide the client with a nonce, which is used as a one time salt. Microsoft's SMB NTLM authentication is a good example, but it has had a lot of problems.
USE SSL, and not just for login. OWASP A9 states that the session id must never be leaked over an insecure channel. After all who cares about the password if you just spill the real authentication credentials a few milliseconds later.
Most people don't implement CSRF protection for login. After all the attacker would have to know the password in the first place, so "session riding" is a moot point.
A slight aside, but in answer to question 3. NO! Also remember that AJAX and standard forms are also just as insecure as one another.
Implementing secure authentication is hard. Unless you are doing it as an academic exercise, i would strongly recommend using the library provided by your framework, if you are lucky enough to have a good one.
You will also need to consider things such as the following, and more.
Implement a suitably random and unguessable session id for use in the session cookie.
Do not allow the session id to be forced.
When permissions or credentials are changed (e.g. because the user has now logged in or out) then
immediately invalidate the session and start a fresh one.
Provide a logout feature, and be sure to invalidate the session upon logout.
Set the cookie to HttpOnly -Preferably require HTTPS and alo set the cookie to secure only.
Consider restricting the session validity to include checking some other information that helps to match the user e.g. user-agent.
Always expire sessions after non-use and do not implement "keep me logged in" by reconnecting the user to their old http session.
Ensure 2 sessions can't have the same session id at the same time
Ensure that all session data is destroyed when a session is invalidated. A new user coming along, may just happen to get assigned a session id that has been used previously. This new session must not have any access to session data that has been set previously against that session id.
If the attacker knows what hashing you are using then they can crack it. And if you want to add a salt you have to send it to the browser and the attacker could intercept it. Using the time as a salt also won't work because there is only a relatively short amount of time so they can solve that as well.
Related
I have a React SPA which makes API calls to a .NET backend. I am currently using JWT authentication. I have implemented the access/refresh token 'pattern'. My problem is that when the page is refreshed, I have to have my tokens stored down somewhere so that, on refresh, the user does not have to log in again to get new tokens. Having spent a fair bit of time researching this issue, it is not clear what the best way of getting around this is.
I have been told that you should not store them down to local storage because they become vulnerable to XSS attacks. A solution which I have come across a few times is to store the tokens in a HTTP-only cookie. Ok - but then I do not see why you don't just use a HTTP-only cookie instead of a refresh token. That is, on log-in, user is issued with relatively long expiry HTTP-only cookie and relatively short expiry access token. On page-refresh, cookie authentication is used to get new access token (if still valid, otherwise user logs in again). I don't mind if, on page refresh, an API call must be made to retrieve a new access token (I just don't want to trigger a user log-in).
I don't understand why a HTTP-only cookie and refresh token might be required, unless it's just to provide another layer of security.
I'm making a simple star rating feature in PHP to my site and my general question is, do cookies prevent people from spamming multiple votes?
As far as I know I can store a cookie with javascript and PHP. What's to prevent the spammer from testing the feature, looking at what cookies are saved and then remove/add them in the spam attack script?
A sub question would be, what should I save in the cookie? That the person has already voted? What's to prevent the spammer from automatically delete all cookies before a spam attack?
So far I've got honeypot, secret code calculated by time and some other things and IP blacklisting.
I will try to stay out of captchas and recaptchas.
Here's the fact: At the worst possible case, a user may get an entire new computer to cheat your system. And there's nothing you can do about it. So no matter which client-side protections you have, they can be broken.
Cookies are trivial to reset.
Sessions rely on cookies, hence, trivial to reset.
IP is easy enough to reset (or use a VPN or some other such service), moreover, mobile devices change IPs as you walk down the street.
The only real way is to authenticate your users (i.e. a login system) and only allow for authenticated users to vote.
Note that a Cookie will probably work for 95% of the cases, if you don't care the occasional cheat here and there. If cheating must be prevented at all costs, you need an authentication system.
Looks like you are talking about anonymous / unauthenticated users (guests) - because if it's logged in users you can validate on server-side much more easily (e.g with Zanderwar's answer on sessions).
I'm sure you already know this rule, but in case you don't know:
Don't do security validations on client side - you never know what browser, mobile or client the user is using. It's very easy to strip aside client side validations, spoof REST variables, encode/decode, replay transactions etc on the modern clients. So don't do security validations on clientside. Client side validation should only be used to enhance the user experience, and proper security validation should be done on server side only.
For unauthenticated, anonymous users I would restrict submissions by IP and time. E.g per IP they can only submit once per hour. You will have to record the IP and time on serverside and reject (or just update) submissions that are too frequent.
This is the simplest solution to your problem I can think of.
There is no way to prevent spam with cookies or sessions. Any time you spend on this concept will be entirely wasted.
That doesn't mean that the session control can not be useful but it can not by itself prevent an experienced user from anything.
Voting sites usually rely either on an authentication system or the client's IP and time stamp to limit users.
Using the browser string together with IP would make it harder but you run the risk of preventing multiple people behind the same firewall (same IP) from voting if they have very similar setup (as you could have in an office)
Aside from that login is another option but could be circumvented by creating multiple accounts.
But preventing multiple votes is always a problem unless you have an existing verified identity of the visitor.
It will never get a full protection without using Captcha or any other anti-bot protection as long as you give guests to use this feature.
The closest you can do, is to block by User-Agent + IP if they vote to much in a certain amount of time.
Another thing, you can do is to find a workaround using JWT authentication. It's a nice tool for client side session management.
Also, you can try and implement a CSRF protection. For example, you can create a unique token when loading the page of the vote, and when a user clicks on one of the stars, the system will send this token along with the vote rating.
But, again, there is no a bulletproof solution for your problem.
I am using ember to write a web ui for a site that requires user to log in. Suppose the browser has stored some cookie from last login of a user. Now the user visits the site again. So, is it a secure and common way for ember to log the user in automatically based on the cookie from the last visit? If so, what are the common ways to implement this? (I can't find anything from Google.) Furthermore, how do I create the cookie upon login? Is it a common way to just put a user id, password hash, and expiration in the cookie?
Additionally, any references related to this subject are greatly appreciated.
Edit 1
In light of Vohuman's answer, I think I can make my question a little more specific. Basically, what I want to know is a common and secure implementation to keep a user logged in, even when they close and reopen the browser. Namely, the life time is beyond the session scope. Take linkedin for example. If you are logged in and exit the browser. Then next time you revisit linkedin, you are still logged in automatically. Right now, what I can picture is a solution like the following.
When you first log in to the site, the server will return a cookie which includes an authentication hash token. Then next time when you revisit the site, the server will receive the hash token and thus authenticate your session.
So, is above flow basically what people usually do to keep a user logged in? If so, is the JSON Web Token (JWT) basically one way to construct the hash token I mentioned above? Additionally, assuming the connection is HTTPS, this approach seems secure to me. Is it not?
Edit 2
This article gives an interesting discussion regarding where to store the access token.
is it a secure and common way for ember to log the user in automatically based on the cookie from the last visit?
Yes and no. Security is a complex topic. Usually session cookies are used for authorizing users. This is actually the most used method of keeping the users logged in. If the user can't keep his credentials secure then any layers of security can be vulnerable.
For Single-page applications usually access tokens are used instead of cookies and sessions. The client sends the user credentials and server returns an access token. The token is encrypted and expirable and can be stored in localStorage or sessionStorage. Using JSON Web Tokens (JWT) standard is a popular method for implementing user authentication and authorization in web services. As an example, the Facebook Open Graph API uses access tokens.
JSON Web Token (JWT) is a compact, URL-safe means of representing
claims to be transferred between two parties. The claims in a JWT
are encoded as a JSON object that is used as the payload of a JSON
Web Signature (JWS) structure or as the plaintext of a JSON Web
Encryption (JWE) structure, enabling the claims to be digitally
signed or integrity protected with a Message Authentication Code
(MAC) and/or encrypted.
edit:
So, is above flow basically what people usually do to keep a user logged in?
For traditional websites, yes.
The whole point of using access tokens is keeping the web service/API stateless. This means that server doesn't have to store any cookies/sessions for authenticating and authorizing users. The stateless is one of the key factors of implementing web services that follow the REST paradigm. It's client that has to store the token and send it to the server (via the Authorization header or query parameters). The server doesn't store the token. Of course, you can store the tokens on the server if you want to add another layer of security, but it's not so common and not necessary. Storing the tokens on the server can also make your application vulnerable to database attacks and is not recommended.
If you want to make the process more secure you can decrease the validity time of access tokens (1 hour, 1 day or 1 week, it's up to you).
As for localStorage, is it secure?
localStorage data are stored separately for each origin (domain). A malicious user can only read the data if he/she has access to the user browser. You should make sure that your app doesn't have any XSS vulnerabilities so malicious users can't inject any scripts to your application. This is actually a different topic.
I wrote a simple demo html (SSL enabled) forms to access some university services thru it. It requires the user to login with his university ID first .
My question is , how to encrypt the logins data even from me the owner of this page ? Is it possible ? so that the user can confidently use this.
You could use HTTP Digest Authentication which does challenge-response authentication and always sends password hashed.
The problem with Digest is that UI for it is ugly and logging out is left up to the browser (you can't have a reliable logout link).
Alternatively you could implement your own challenge-response mechanism in JavaScript, e.g. http://code.google.com/p/crypto-js/
but it's rather pointless, because the user doesn't have any guarantee that you're doing it, and that you won't replace the secure script with an insecure one in the future. As the site owner (or somebody that hacks your site) you could change the script and "steal" passwords at any time.
SSL is good. That's the best real security you can do client-side.
You can ensure that you're storing passwords securely on server-side — hash it with a slow hash such as bcrypt (not md5/sha1) and use unique salt for every password.
I create js app with Backbone and RequireJS for registred or non registred users. To retrive data from database I use simple JSON web service and of course some of methods are not avaiable for quest. Problem is that I don't know where or how I should store auth data retrive from server without reloading it in every view. Should I use cookies ?
I guess it depends on your authentication, authorization methods as well as the kind of security you need to consider for your users. If you're trying to be RESTful, you can't have sessions to save state (at least server-side). You could, but it wouldn't be RESTful due to saving of state on the server, if that matters to you. I've heard that it is okay to save state client-side but from what I've read, I'm not sure how the community feels about certain implementations that take this approach. (Like cookies, I'll revisit this later.)
Say you have someone login with username and password. You can hold that information in your Backbone app, maybe you have a model called AUTH that does this. Each time you make a request to the server you'd send that data each trip at which point the server authenticates and gives or rejects access to given resources. If you use Basic Auth this information would be in the header I think. Using SSL mitigates some of the major security concerns surrounding the sending of this information over the wire and for the rest of the discussion let's assume this is what we are using.
The other way that you could do this is to use encrypted cookie, encrypted cookie sessions. This is what I do with my current application. Honestly, I don't know if this is considered a violation of RESTful principles or not. The general chatter on the web seems to be a lot of "cookies bad, sessions bad" with some people saying, "get real." Using cookies would expose you to cookie hijacking if someone had access to the users computer, but depending on your application and the security needs it might not be an unreasonable option. It works for me and if it isn't RESTful, I like to call it RESTLike.
To close I'll just describe my setup. It would be nice to get your thoughts as well as the Stack's opinions on this also.
Basically I have a setup where when someone goes to the main page, the server checks for the encrypted cookie session. If the cookie session is invalid or non-existent, it gives the user the regular page with a chance to login. When they login, I send that information over POST so it's in the body of the request rather than the URI. (This is technically a violation of the REST HTTP verb concept since you use POST to save a resource.) When that information is processed, check the username, pass hash created by a unique salt, then the server creates an encrypted session cookie and passes it back to the user. Now, each time my user hits a route that requires authentication, the server checks the cookie to make sure it is still valid (time limit, user information, etc.) and if so - allows access. If not, it destroys the cookie information and sends back an appropriate status code. The backbone app reacts to this by resetting any view and data that shouldn't be in the hands of an unauthenticated user and shows them the login screen.
Hope this gives you an idea. This is the answer to how I do it, but if someone has criticisms or better ideas I'd be happy to upvote them instead.